I am currently writing a online game. Now I have to check if an event happen (checking timestamp in database) and depending on that execute some actions. I have to check for an event every second.
I wanted to use a cronjob but with cron you can run a script only every minute.
My idea was to use cron and loop 60 times in my php script. But I think this isn't the best solution.
So whats the best way to run a script every second?
I searched for a better solution but it seems that my first idea, with clean code, is the best solution.
This is my current code:
<?php
set_time_limit(60);
$start = time();
for ($i = 0; $i < 59; ++$i) {
// Do whatever you want here
time_sleep_until($start + $i + 1);
}
?>
Why not modify the script so that it just repeats the code every second? This will reduce the parsing overhead and be less complicated.
You should probably run the script once, and use a loop with delay to accomplish your desired timing.
The side benefit is that this is more efficient, and you would only have to open resources (ie, databases) once.
You shouldn't want this :P. No host will accept your cronjob is running every second every minute?
You can save the time it runned in a database, and the next time you run it calculate the time between both runs and do the calculations you want. every second is a very bad idea.
$total_time = 0;
$start_time = microtime(true);
while($total_time < 60)
{
//DoSomethingHere;
echo $total_time."\n";
//sleep(5);
$total_time = microtime(true) - $start_time ;
}
add this in crontab to run every minute.
Related
I am trying to start several processes as close to the same time as possible. A cronjob selects all items to be processed from the database a minute prior to the actual time these processes need to start, and then starts a child process for each record found.
As it can take several seconds to run through the database and spawn the child processes, I am trying to create a sleep or usleep delay so that each spawned child process starts as close as possible to the top of the next minute.
In testing, I have noticed some differences between the child start times returned by time() and microtime().
Here's the code I have to create the delay:
$unixtime_now = time();
$unixMicrotime_now = microtime(true);
$timeToStart = $unixtime_now + 2;
$timeToSleep = $timeToStart - $unixMicrotime_now;
$timeToSleep = number_format($timeToSleep,6);
$timeToSleep = str_replace('.','',$timeToSleep);
usleep ($timeToSleep);
$startedAtMicrotimeFloat = microtime(true);
$startedAtTime = time();
$date1 = date("H:i:s", $startedAtMicrotimeFloat);
$date2 = date("H:i:s", $startedAtTime);
echo "Unixtime Now = $unixtime_now<br />UnixMicroTime Now = $unixMicrotime_now<br />Time to Start = $timeToStart<br />Time to Sleep = $timeToSleep<br />Started at Time = $startedAtTime - $date2<br />Started at MicroTimeFloat = $startedAtMicrotimeFloat - $date1";
Note that I used 2 seconds rather than 60 seconds for the offset to facilitate speed in testing.
2 questions:
1) No matter how many times I run this, the times returned by time() are ALWAYS 1 second before the times returned by microtime(). For example:
Started at Time = 1555765444 - 09:04:04
Started at MicroTimeFloat = 1555765445.0002 - 09:04:05
This is probably a forest for the trees issue, but does anyone have an idea why this is or how I can resolve it?
2) Are there any drawbacks to having a usleep() delay that can be as long as 59 seconds? Would it be better to use sleep() and accept the the child processes might start at 1555765445.9999 - 09:04:05 rather than 1555765445.0002 - 09:04:05, or up to almost a full second later?
Thanks in advance.
Alan
Per Dave's suggestion, I edited the code as follows:
$date1 = date("H:i:s", microtime(true));
$date2 = date("H:i:s", time());
I still get the same result:
Started at Time = 1555876342 - 15:52:22
Started at MicroTimeFloat = 1555876343.0003 - 15:52:23
The microtime() result, which I suspect to be accurate, is later than the time() result by 1.0003 seconds.
I have created two functions in a separate php file and want them to run over and over.
After function A completes, I want it to compare the current time, relative to the last time function B ran, and if more than 24hrs has elapsed (or whatever value I set it to), it runs function B, resets the next time for when it should be trigger to run, and continues to run function A. They need to run separately and not parallel since values altered in function A will affect function B and thus need to be separate. The ideal scenario is I have a config.php file where I set the time delay (in hours), but I can sort that out later!
I am stumped on how to get this while(true){} loop organized... any ideas?
Regardless of whether you end up doing it this way (because I think the comments about cron make some good points, and there are some other issues you may run into with a continuously running PHP script like this) here's a basic logic for executing the alternate function based on a defined delay.
// define the delay and initialize the timestamp
$delay = 86400; // 24 hours, for example
$last_time = time();
while (true) {
functionA();
// the next time functionB should execute is the timestamp for the last run + the delay
if (time() > $last_time + $delay) {
functionB();
$last_time = time(); // reset the timestamp
}
}
Would something of this nature be similar to what you're looking for?
while ($time > 13 && $time < 21)
You could have flags involved in each function as well. If a boolean flag is fired and is = 1, then continue on?
I have a script PHP which do requests on MYSQL server, and I want to execute itself once a day!
The first time, I execute the script myself.
And I want the script, at the end of the execution, choose a random time in the day, between 8:30AM and 7:30PM, and reexecute itself automatically the day after, at this time. Is it possible?
To choose a time randomly I have coded like this:
$tomorrow = new DateTime(date('Y-m-d H:m:s', time()+86400));
$tomorrow1 = $tomorrow -> setTime(8,30,0);
$tomorrow2 = $tomorrow -> setTime(19,30,0);
$min_time = strtotime($tomorrow1->format('Y-m-d H:m:s'));
$max_time = strtotime($tomorrow2->format('Y-m-d H:m:s'));
$rand_time = rand($min_time, $max_time);
But then I don't know how to do an automatic execution for the script at this time. Maybe I can pause like this:
sleep ($rand_time - time());
But I don't know how to reexecute the script after that. And I don't think sleep is the best solution. Do you if there is a way and how to do this?
Allright, I can use cron, but the issue still remains: I need to be able to modify the task scheduler for the day after everyday by the php file itself!
The approach taken by e.g. APT::Periodic is to start the job at a fixed time (in your case 08:30) and sleep for a random period of time as the first command in your job (in your case for $(($RANDOM % 39600)) seconds, assuming your shell is Bash).
This avoids the need to write anything to the crontab.
I don't know PHP, but I think it would look something like:
#/usr/bin/php
// Wait 0-11 hours before starting (invoked by cron at 0830)
sleep(rand(0, 39600));
// It's now a time between 0830 and 1930
// rest of your code here
and your crontab would be simply
30 8 * * * /path/to/my/script
Alternatively, don't sleep at all in your script, but do the sleep in the crontab command:
SHELL=/bin/bash
30 8 * * * sleep $(($RANDOM % 39600)) && /path/to/my/script
This may be preferable if you ever need to execute the script by hand (and not want to wait up to 11h for it to start).
I want to put a php daemon to sleep (with System_Daemon::iterate())
so it runs max 20 times randomly spread over an hour. maybe a min distance would be smart so it doesn't run 20 times in the first half hour and 0 times in the second half.
i'm kinda stuck here and don't know how to start with this one, any help is very apreciated!
You may use cron jobs, to set the script to run ever so often.
http://net.tutsplus.com/tutorials/php/managing-cron-jobs-with-php-2/
... Crontab:
0 9 * * * /path/to/bashscript
and in /path/to/bashscript:
#!/bin/bash
maxdelay=$((1*60)) # every hour, converted to minutes
for ((i=1; i<=20; i++)); do
delay=$(($RANDOM%maxdelay)) # pick an independent random delay, 20 times
(sleep $((delay*60)); /path/to/phpscript.php) & # background a subshell, then run the php script
done
i came up with one possible solution, i didnt try it out yet, so it main contain syntax or logic errors. because it is running as a daemon there is a never ending loop around it.
// 3600 seconds or one hour
$timeframe=3600;
// run max 20 times in $timeframe
$runtimes=20;
// minimum delay between two executions
$mindelay=60;
// maxium delay between two executions
$maxdelay=240;
if ($cnt % $runtimes != 0) {
$delay = rand($mindelay,$maxdelay);
System_Daemon::iterate($delay);
$sum += $delay;
$cnt++;
} else {
//final delay till the $timeframe
if ($sum < $timeframe) {
System_Daemon::iterate($timeframe - $sum);
}
$sum=0;
}
its not perfect and u waste some time but i guess its going to fullfill the job.
any comments?
I tried using it like this:
$now = microtime(true);
// cpu expensive code here
echo microtime(true) - $now;
but regardless of what code I enter between these statements, I alwasy get almost the same results, something like 3.0994415283203E-6
What am I doing wrong?
Better solution. Run the code multiple times to average out the operation:
$runs = 500;
$start = microtime(true);
for ($i = 0; $i < $runs; $i++) {
//cpu expensive code here
}
$end = microtime(true);
$elapsed = number_format($end - $start, 4);
$one = number_format(($end - $start) / 500, 7);
echo "500 runs in $elapsed seconds, average of $one seconds per call";
3.0994415283203E-6 equates to 0.0000030994415283203.
The E-6 tells you to move the decimal point left six places. E+6 would mean the opposite. As #deceze mentioned, this is called scientific notation.
If you're doing a performance test, it's a good idea to put the code into a 100000 or so iteration loop, and then divide the resulting time by 100000. That way you get a more accurate average.
You're not doing anything wrong, it's just that the code you're timing really only takes a fraction of a second to run.
If you want to prove it, sleep for a few seconds.
It looks like you are using microtime() without the optional argument, but you say you are, so I am not 100% sure.
What is the output of this:
$now = microtime(true);
sleep(1);
echo microtime(true) - $now;
PHP always amazes me with how fast it is. Your code seems to be right. Maybe your code is really only taking 3 milliseconds.
You could try making a long loop, something like this:
$x=0;
while ($x<1000000)
{
$x++;
}
Add this code inside of your timer. For me, looping 1 million times usually takes about 1/2 second. See if this changes your time.