Re: [PATCH] Microsecond resolution and accuracy on Windows
| From: | Matt Wilmas | Date: | Fri, 05 Sep 2014 17:20:20 +0000 |
| Subject: | Re: [PATCH] Microsecond resolution and accuracy on Windows | ||
| References: | 1 2 | Groups: | php.internals php.internals.win |
| Request: | Send a blank email to internals-win+get-1068@lists.php.net to get a copy of this message | ||
Hi Anatol!
----- Original Message -----
From: "Anatol Belski"
Sent: Tuesday, September 02, 2014
Hi Matt, On Mon, September 1, 2014 20:36, Matt Wilmas wrote:Thanks for all the feedback! I was just waiting to get something "solid" before replying. :-) I was like, "Well, hell," when I saw this first reply. :*( BUT, I think it's fixed now! Patch updated (at links above for anyone). I just quickly implemented what I had in my mind for a while Sat. morning (half the time was trying to consider what would happen in different scenarios), so I didn't spend much time on it at all. :-) Brief checking after, but yep, I was able to reproduce your result (XP, real system) after a few minutes (15-20 max) and realized what was happening. I thought about and tried a few things in the following couple days, before settling (more "obviously" now) on what's there now ("computed" out-of-valid-range logic was too simple before, oops). Maybe THIS is actually the correct logic I had in mind last October! I haven't seen any problem with it after hours and hours (which seems right). The only time there could be t1 < t0 is if the clock is set backwards (which obviously happens now with the current low-res version).Hi all! I'm back after several years, and will have a few more changes for Windows, at least. (It was CVS back then, so I still have to figure some things out... Just had to edit files on Github site. :-/) Anyway, this patch is for microtime, etc. on Windows XP-7. In March 2013, the fix for bug #64370 reduced the resolution to 1/64 or 1/100 of a second or so -- hardly "micro" time. :*( See also bugs #64633 and #65626. The highest resolution time function available before Windows 8 has simply been used by itself since then. High-resolution Performance Counters were always used until then, but in a way that may become inaccurate and error-prone on some Windows+(virtual) hardware combinations. One problem with the long-standing previous Performance Counter implementation is that it tried to be monotonic (always increasing). But gettimeofday() IS supposed to be affected by changes in system time. Another problem was assuming that Performance Counters would track at a nearly-perfect rate with the real clock even without system time changes. The solution to have high-resolution like the past, and accuracy like now (after #64370 fix) is fairly simple and straightforward: Use Performance Counters, but check that the value is within "range" of the real, current time! With this implementation, you get high-resolution at least over short periods (e.g. when it matters) AND accuracy over a longer time between calls (e.g. won't notice few milliseconds of lost resolution), with no buggy/incorrect times. (It seems there *could* be a Counter synchronization issue between multiple cores/processors on *some* hardware on *XP*. I don't think this is a concern, nor related to previous bugs? http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85) . aspx#qpc_support_in_windows_versions ) It's much more optimized than what's there now, and slightly over the old implementation. Not sure if I should give the saved patch link, or the "live compare" (?) on Github, so I'll do both for now: http://realplain.com/php/microtime_5_4.diff https://github.com/matt-moo/php-src/compare/PHP-5.4.diff Against 5.4 since that's what I quickly worked on so it's ready for the next 5.4 release (Stas?). (Although I guess we're supposed to change the oldest branch usually?) What do you think? Questions or comments?unfortunately the patch doesn't fix the both issues, a quick test shows just a return to the old behaviour:php -n -r "$t0 = microtime(true); do { $t1 = microtime(true); echo $t1 -$t0, PHP_EOL; } while($t1 >= $t0 && ($t0 = $t1));" .......................................... 4.7922134399414E-5 4.6968460083008E-5 4.7922134399414E-5 4.8160552978516E-5 4.7922134399414E-5 4.7922134399414E-5 4.8160552978516E-5 4.887580871582E-5 0.00020909309387207 -0.015614986419678 I took an arbitrary win7 VM for that. The error happens after a couple of seconds of running. That's just before starting to argue. We probably would get WTFs from the users which had this before and had that fixed. IMHO, it's still better not to have $t1 < $t0 even with worse accuracy.
I still think that this issue is unsolvable within PHP. Fixing this for one group of users will break it for another. There are too many factors affecting this. Besides the hardware we cannot affect, there are programs affecting the behaviour (for example some could use SetSystemTimeAdjustment()).See if you can break/find a problem with it now, please. :-)
And that is IMO the main mistake with this approach (and the one before removing QPC) - it's that QPC is based on an independent source, while GetSystemTimeAdjustment and similar time functions are synchronizable to an external source. Haven't tried, but just asking - would it work correct on day light saving days? QPC doc also states it is dedicated for time intervals measurements. The user would think that he gets a real correct microtime timestamp, while in reality it's a "computed" one, but the equation used for the computation is far incomplete.By "it," you mean my/any QPC implementation with DST changes? Yes, GetSystemTime... is like time() I assume and doesn't change with DST -- otherwise PHP's date stuff would be affected. And my version of course always respects the currently-reported time, anyway, unlike the OLD version.
Inbetween i was developing pecl.php.net/hrtime which uses APIs similar to QPC on linux. While testing it even on linux we have seen a shift between gettimeofday and monotonic clocks. Well, there one needs much longer time to reproduce and in reality one doesn't know which of those APIs exactly has a bug. But just as an example.Yeah, I saw about your hrtime package in the one bug comment (interesting), but haven't looked at it yet...
At the end - I would not include this patch that fast especially shortly before the PHP-5.4 doors are closing afterwards. While it were of course amazing to have a fix, the patch doesn't seem to fix the bad accuracy but brings the old behavior back. I have also a couple of notes to the code, i'd leave my comments on the patch repo. Matt, I have anyway to thank you for the effort and energy you spent on this.Still hoping for 5.4 for at least the "security" related view with uniqid(). :-) BTW, I also removed the useless modulo from microtime(). (The GitHub patch is breaking the uniqid.c header... ignore.)
Regards AnatolThanks again, Matt