php time() and microtime() do sometimes not concor

2019-02-17 14:08发布

问题:

While logging some data using microtime() (using PHP 5), I encountered some values that seemed slightly out of phase in respect to the timestamp of my log file, so I just tried to compare the output of time() and microtime() with a simple script (usleep is just here in order to limit the data output):

<?php
for($i = 0; $i < 500; $i++) {
    $microtime = microtime();
    $time = time();
    list($usec, $sec) = explode(" ", $microtime);
    if ((int)$sec > $time) {
        echo $time . ' : ' . $microtime . '<br>';
    }
    usleep(50000);
}
?>

Now, as $microtime is declared before $time, I expect it to be smaller, and nothing should ever be output; however, this obviously is not the case, and every now and then, $time is smaller than the seconds returned from microtime(), as in this example (truncated) output:

1344536674 : 0.15545100 1344536675
1344536675 : 0.15553900 1344536676
1344536676 : 0.15961000 1344536677
1344536677 : 0.16758900 1344536678

Now, this is just a small gap; however, I have observed some series where the difference is (quite) more than a second... so, how is this possible?

回答1:

If you look at the implementations of time and microtime, you see they're radically different:

  • time just calls the C time function.
  • microtime has two implementations: If the C function gettimeofday is available (which it should be on a Linux system), it is called straight-forward. Otherwise they pull of some acrobatics to use rusage to calculate the time.

Since the C time call is only precise up to a second, it may also intentionally use a low-fidelity time source.

Furthermore, on modern x86_64 systems, both C functions can be implemented without a system call by looking into certain CPU registers. If you're on a multi-core system, these registers may not exactly match across cores, and that could be a reason.

Another potential reason for the discrepancies is that NTPd(a time-keeping daemon) or some other user-space process is changing the clock. Normally, these kinds of effects should be avoided by adjtime.

All of these rationales are pretty esoteric. To further debug the problem, you should:

  • Determine OS and CPU architecture (hint: and tell us!)
  • Try to force the process on one core
  • Stop any programs that are (or may be) adjusting the system time.


回答2:

This could be due to the fact that microtime() uses floating point numbers, and therefore rounding errors may occur.

You can specify floating point numbers' precision in php.ini