0

On my machine, the PHP program

<?php
$now= time();
echo "Now:        ".$now."\n";
$waituntil= $now+5;
echo "Wait until: ".$waituntil."\n";
time_sleep_until($waituntil);
echo "Now:        ".time()."\n";
?>

produces an output such as

Now:        1492614718
Wait until: 1492614723
Now:        1492614722

Now I am wondering why the time_sleep_until function did not wait until the specified time (it always continues one second before the specified time).

How can I achieve that the program waits until the specified linux timestamp?

EDIT: I added microtime(true) and now get the following result:

<?php
$now= time();
$nowmicro= microtime(true);
echo "Now:        ".$now."\n";
echo "Now micro:  ".$nowmicro."\n";
$waituntil= $now+5;
echo "Wait until: ".$waituntil."\n";
time_sleep_until($waituntil);

$now= time();
$nowmicro= microtime(true);
echo "Now:        ".$now."\n";
echo "Now micro:  ".$nowmicro."\n";
?>

produces

Now:        1492616333
Now micro:  1492616333.1153
Wait until: 1492616338
Now:        1492616337
Now micro:  1492616338.0001
phinz
  • 1,225
  • 10
  • 21

3 Answers3

2

time_sleep_until uses microtime. If you'll use microtime(true) instead time() you'll get proper results:

Now:        1492615646.9312
Wait until: 1492615651.9312
Now:        1492615651.9313

time() and microtime() are different, see more information here: https://stackoverflow.com/a/11890155/994054

Proof:

...
time_sleep_until($waituntil);
echo "Now:        ".microtime(true)."\n";
echo "Now:        ".time()."\n";

gives me

Wait until: 1492615871
Now:        1492615871.0001
Now:        1492615870

I don't know exact reason why time() gives different result after you use time_sleep_until, you would have to dig down into PHP C code

Also it's worth to mention good alternative for time_sleep_until() is usleep

Community
  • 1
  • 1
Peter
  • 16,453
  • 8
  • 51
  • 77
1

Running this myself, I get the following result:

Now: 1492615301 
Wait until: 1492615306 
Now: 1492615306

What PHP version are you running on? I understand this function didn't play nice on Windows in the earlier versions (pre-5.3)

Michael
  • 59
  • 6
  • My PHP version is "PHP 5.6.29-0+deb8u1 (cli) (built: Dec 13 2016 16:02:08)" and I am on Debian 8. At least, I now know that it works as expected on your machine. – phinz Apr 19 '17 at 15:25
  • Interesting. If you are always using the same offset, perhaps using sleep() directly would be a better alternative? – Michael Apr 19 '17 at 15:28
  • I can't use sleep because of a time shift in loops, see my comment on Victor's answer. I will check the offset several times now. – phinz Apr 19 '17 at 15:33
  • Yeah I think your best bet is the microtime solution. I'm not sure why it works though. Possibly an issue with rounding? If you start in the middle of a tick, perhaps its enough to change the offset by < 1s – Michael Apr 19 '17 at 15:39
  • Yes, it seems that `time` and `microtime` produce inconsistent results. – phinz Apr 19 '17 at 15:43
0

Maybe, better solution is to set timeout using sleep function? More you can find here.

So, your code will look like this:

<?php
$now= time();
echo "Now: $now".PHP_EOL;
$sleepTimeout= 5;
echo "Sleep timeout: $sleepTimeout".PHP_EOL;
sleep($sleepTimeout);
echo "Time after sleep: ".time().PHP_EOL;
?>

Regards.

Viktor
  • 819
  • 1
  • 12
  • 26
  • 1
    I wanted to use this to loop some commands every 5 seconds for logging and before I was using sleep but after some time, the time that php takes to execute the remaining commands in the loop matter and then there is a time shift. I thought `time_sleep_until` is the solution... – phinz Apr 19 '17 at 15:31