Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
-Original Message- From: gvanros...@gmail.com [mailto:gvanros...@gmail.com] On Behalf Of Guido van Rossum Sent: 2. apríl 2012 17:43 To: Kristján Valur Jónsson Cc: Cameron Simpson; Python Dev Subject: Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()? You seem to have missed the episode where I explained that caching the last value in order to avoid going backwards doesn't work -- at least not if the cached value is internal to the API implementation. Yes, and I can't find it by briefly searching my mail. I haven't had the energy to follow every bit of this discussion because it has become completely insane. Of course we cannot promise not moving backwards, since there is a 64 bit wraparound some years in the future. Otherwise, evidence contradicts your claim. Here's actual code from production: BOOL WINAPI QueryPerformanceCounterCCP( LARGE_INTEGER* li ) { static LARGE_INTEGER last = {0}; BOOL ok = QueryPerformanceCounter(li); if( !ok ) { return FALSE; } if( li-QuadPart last.QuadPart ) { last = *li; } else { *li = last; } return TRUE; } This has been running for many years on an incredible array of hardware and operating systems. However, we mostly don't do this caching anymore, this code is a rudiment. In all other places, a straight QPC is good enough for our purposes. Even negative delta values of time are usually harmless on the application level. A curiosity, but harmless. I am offering empirical evidence here from hundreds of thousands of computers over six years: For timing and benchmarking, QPC is good enough, and will only be as precise as the hardware and operating system permits, which in practice is good enough. Which is why am flabbergasted by all of this bikeshedding. My original submission (http://bugs.python.org/issue10278) Is merely a suggestion to provide a standardised clock function, useful for measuring the delta-t to the best abilities of the platform. This is incredibly useful in many areas and necessary because time.clock() currently means different things on different operating systems. There is no need to try to overspecify this to become something which it never can be. If someone wants a real time clock with no time slew to control a radio telescope, he better write his own interface to an atomic clock. What he definitely shouldn't be doing is using a built in timer on an old computer with an old operating system. Also, since you objected to the original suggestion of time.wallclock(), here is the definition from Wikipedia: http://en.wikipedia.org/wiki/Wall_clock_time . I actually never read this before, but it agrees with my original definition of relative passage of time in the real world. I got the term myself from using profiling tools, which measure program execution in cpu time or wallclock time. Cheers, Kristján ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
You seem to have missed the episode where I explained that caching the last value in order to avoid going backwards doesn't work -- at least not if the cached value is internal to the API implementation. Yes, and I can't find it by briefly searching my mail. I haven't had the energy to follow every bit of this discussion because it has become completely insane. I'm trying to complete the PEP, but I didn't add this part yet. Of course we cannot promise not moving backwards, since there is a 64 bit wraparound some years in the future. Some years? I computed 584.5 years, so it should not occur in practice. 32-bit wraparound is a common issue which occurs in practice on Windows (49.7 days wraparound), and I propose a workaround in the PEP (already implemented in the related issue). Here's actual code from production: BOOL WINAPI QueryPerformanceCounterCCP( LARGE_INTEGER* li ) { static LARGE_INTEGER last = {0}; BOOL ok = QueryPerformanceCounter(li); if( !ok ) { return FALSE; } Did you already see it failing in practice? Python ignores the return value and only uses the counter value. Even negative delta values of time are usually harmless on the application level. A curiosity, but harmless. It depends on your usecase. For a scheduler or to implement a timeout, it does matter. For a benchmark, it's not an issue because you usually repeat a test at least 3 times. Most advanced benchmarked tools gives a confidence factor to check if the benchmark ran fine or not. I am offering empirical evidence here from hundreds of thousands of computers over six years: For timing and benchmarking, QPC is good enough, and will only be as precise as the hardware and operating system permits, which in practice is good enough. The PEP contains also different proofs that QPC is not steady, especially on virtual machines. Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Victor Stinner wrote: You seem to have missed the episode where I explained that caching the last value in order to avoid going backwards doesn't work -- at least not if the cached value is internal to the API implementation. Yes, and I can't find it by briefly searching my mail. I haven't had the energy to follow every bit of this discussion because it has become completely insane. I'm trying to complete the PEP, but I didn't add this part yet. Of course we cannot promise not moving backwards, since there is a 64 bit wraparound some years in the future. Some years? I computed 584.5 years, so it should not occur in practice. 32-bit wraparound is a common issue which occurs in practice on Windows (49.7 days wraparound), and I propose a workaround in the PEP (already implemented in the related issue). Here's actual code from production: BOOL WINAPI QueryPerformanceCounterCCP( LARGE_INTEGER* li ) { static LARGE_INTEGER last = {0}; BOOL ok = QueryPerformanceCounter(li); if( !ok ) { return FALSE; } Did you already see it failing in practice? Python ignores the return value and only uses the counter value. Even negative delta values of time are usually harmless on the application level. A curiosity, but harmless. It depends on your usecase. For a scheduler or to implement a timeout, it does matter. For a benchmark, it's not an issue because you usually repeat a test at least 3 times. Most advanced benchmarked tools gives a confidence factor to check if the benchmark ran fine or not. I am offering empirical evidence here from hundreds of thousands of computers over six years: For timing and benchmarking, QPC is good enough, and will only be as precise as the hardware and operating system permits, which in practice is good enough. The PEP contains also different proofs that QPC is not steady, especially on virtual machines. I'm not sure I understand what you are after here, Victor. For benchmarks it really doesn't matter if one or two runs fail due to the timer having a problem: you just repeat the run and ignore the false results (you have such issues in all empirical studies). You're making things needlessly complicated here. Regarding the approach to try to cover all timing requirements into a single time.steady() API, I'm not convinced that this is good approach. Different applications have different needs, so it's better to provide interfaces to what the OS has to offer and let the application decide what's best. If an application wants to have a monotonic clock, it should use time.monotonic(). The OS doesn't provide it, you get an AttributeError and revert to some other function, depending on your needs. Having a time.steady() API make this decision for you, is not going to make your application more portable, since the choice will inevitably be wrong in some cases (e.g. going from CLOCK_MONOTONIC to time.time() as fallback). BTW: You might also want to take a look at the systimes.py module in pybench. We've been through discussions related to benchmark timing in 2006 already and that module summarizes the best practice outcome :-) -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, Apr 03 2012) Python/Zope Consulting and Support ...http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/ 2012-04-03: Python Meeting Duesseldorf today ::: Try our new mxODBC.Connect Python Database Interface for free ! eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 http://www.egenix.com/company/contact/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
-Original Message- From: python-dev-bounces+kristjan=ccpgames@python.org Some years? I computed 584.5 years, so it should not occur in practice. Funny that you mention it. should not occur in practice is exactly my point. Here's actual code from production: BOOL WINAPI QueryPerformanceCounterCCP( LARGE_INTEGER* li ) { static LARGE_INTEGER last = {0}; BOOL ok = QueryPerformanceCounter(li); if( !ok ) { return FALSE; } Did you already see it failing in practice? Python ignores the return value and only uses the counter value. No, actually not. But we always check return codes. Always. Even negative delta values of time are usually harmless on the application level. A curiosity, but harmless. It depends on your usecase. For a scheduler or to implement a timeout, it does matter. Does it? now = time.wallclock() if job.due_time = now: job.do_it() So what if you get an early timeout? timeouts aren't guaranteed to wait _at least_ the specified time. Rather to wait _at most_ the specified time. The PEP contains also different proofs that QPC is not steady, especially on virtual machines. What does steady mean? Sampled time on a computer will always differ from some ideal time measured by an atomic clock. On a virtual machine, the probability distribution of the error function can be different than on a real machine, but saying it is different is not enough. You have to quantify it somehow. And unless there is some accepted error PDF, there is no way to say that some platforms are ok, and others not. And what does it matter? A virtual machine is just another platform, one where we are providing a counter as good as that platform can provide. Caveat emptor: Don't expect reliable benchmarks or smoothly running time on a virtual machine. The wallclock() function will contain some undetermined error depending on the quality of your platform. I think you are simply overcomplicating the problem and trying to promise too much, without even being able to properly quantify that promise. Just relax the specification and all will be well. K ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On 30 March 2012 21:52, Guido van Rossum gu...@python.org wrote: Oh dear. I really want to say that 15 ms is good enough. Some possible exceptions I can think of: - Profiling. But this really wants to measure CPU time anyways, and it already uses a variety of hacks and heuristics to pick the best timer, so I don't really care. That depends on what you're profiling. If you're profiling CPU bound algorithms then yes CPU time is better. But if your trying to profile/measure hardware device/comms performance for example then CPU time is of no interest. There, on windows the 15ms resolution of time.time makes it useless. For some reason I always forget this and sit looking at trace outs for 5 minutes wondering why everything takes either 0, 15, or 30ms. For nearly all my use cases I'm not terribly interested in monotonicity, or stability in suspend/resume states so I won't give my opinions on thiose (though I can see they are good things and can well imagine needing them one day), I just want an easy way of getting at least micro second resolution cross platform. I don't mind particularly what you call it but FWIW 'highres' seems a bit odd to me. It seems that highres is likely to seem lowres one day, and then you need to add higherres() and then evenhigherthanthatres(). I would go with microtime(), or nanotime() it doesn't make any promises about anything other than the resolution. Sam ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Mon, Apr 2, 2012 at 2:31 AM, Sam Partington sam.parting...@gmail.com wrote: On 30 March 2012 21:52, Guido van Rossum gu...@python.org wrote: Oh dear. I really want to say that 15 ms is good enough. Some possible exceptions I can think of: - Profiling. But this really wants to measure CPU time anyways, and it already uses a variety of hacks and heuristics to pick the best timer, so I don't really care. That depends on what you're profiling. If you're profiling CPU bound algorithms then yes CPU time is better. But if your trying to profile/measure hardware device/comms performance for example then CPU time is of no interest. There, on windows the 15ms resolution of time.time makes it useless. For some reason I always forget this and sit looking at trace outs for 5 minutes wondering why everything takes either 0, 15, or 30ms. For nearly all my use cases I'm not terribly interested in monotonicity, or stability in suspend/resume states so I won't give my opinions on thiose (though I can see they are good things and can well imagine needing them one day), I just want an easy way of getting at least micro second resolution cross platform. I don't mind particularly what you call it but FWIW 'highres' seems a bit odd to me. It seems that highres is likely to seem lowres one day, and then you need to add higherres() and then evenhigherthanthatres(). I would go with microtime(), or nanotime() it doesn't make any promises about anything other than the resolution. You're being altogether too reasonable about it. :-) People keep asking for a clock that has nanosecond precision and yet will tell time accurately for centuries, without ever skipping forward or backward... -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
At least on some versions of Windows (e.g. XP) the QueryPerformanceCounter()-API is more or less only a stub around a call to RDTSC which in turn varies in frequency on (at least) Intel Pentium 4, Pentium M and Xeon processors (bound to the current clock frequencies). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
-Original Message- From: python-dev-bounces+kristjan=ccpgames@python.org [mailto:python-dev-bounces+kristjan=ccpgames@python.org] On Behalf Of Cameron Simpson Sent: 30. mars 2012 21:43 There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution - no steps no steps is something unquantifiable. All time has steps in it. What you mean here is no 'noise'. And this is also never actually achievable. A clock that ticks forwards, but sometimes stops some and then ticks some more, is simply a clock with a lower resolution on average than what can be observed for certain time periods. It befuddles me somewhat how complicated you are making all of this. Simply provide the best high resolution, non-backwards ticking, performance timer that the platform provides, and don't try to make promises about unquantifiable things such as 'steps'. You can do this simply using QPC on windows and enforcing the forward ticking using a static local. Simply promise that this is a forward ticking clock with the highest resolution and lowest noise available for the platform and make no other guarantees, other than perhaps suggesting that this might not be used reliably for benchmarking on older os/hardware platforms. K ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
You seem to have missed the episode where I explained that caching the last value in order to avoid going backwards doesn't work -- at least not if the cached value is internal to the API implementation. 2012/4/2 Kristján Valur Jónsson krist...@ccpgames.com: -Original Message- From: python-dev-bounces+kristjan=ccpgames@python.org [mailto:python-dev-bounces+kristjan=ccpgames@python.org] On Behalf Of Cameron Simpson Sent: 30. mars 2012 21:43 There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution - no steps no steps is something unquantifiable. All time has steps in it. What you mean here is no 'noise'. And this is also never actually achievable. A clock that ticks forwards, but sometimes stops some and then ticks some more, is simply a clock with a lower resolution on average than what can be observed for certain time periods. It befuddles me somewhat how complicated you are making all of this. Simply provide the best high resolution, non-backwards ticking, performance timer that the platform provides, and don't try to make promises about unquantifiable things such as 'steps'. You can do this simply using QPC on windows and enforcing the forward ticking using a static local. Simply promise that this is a forward ticking clock with the highest resolution and lowest noise available for the platform and make no other guarantees, other than perhaps suggesting that this might not be used reliably for benchmarking on older os/hardware platforms. K -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Apr 2, 2012, at 10:39 AM, Kristján Valur Jónsson wrote: no steps is something unquantifiable. All time has steps in it. No steps means something very specific when referring to time APIs. As I recently explained here: http://article.gmane.org/gmane.comp.python.devel/131487/. -glyph ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Sat, Mar 31, 2012 at 8:46 AM, Guido van Rossum gu...@python.org wrote: Given the amount of disagreement I sense, I think we'll need to wait for more people to chime in. I currently can't imagine why I *personally* would want anything better than what we currently call time.time. For that reason, I like Cameron's proposal best. If and when I have a use case, I'll be able to query the system for the clock that has the best combination of desirable properties. Admittedly, by then the answer probably will be time.time.wink/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On 03/31/2012 12:47 AM, Victor Stinner wrote: Can you go into more detail about QPC()'s issues? Yes, see the PEP: http://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter FYI, Victor, the PEP is slightly incomplete. Not that this is your fault--you've done your homework. But I've actually lived through it. I was a professional Win32 developer for 15 years, and I attempted to write a game on Windows back in the early-mid 2000s. On Windows XP, QPC /usually/ uses the ACPI timer in my experience, but sometimes uses RDTSC. Both of these had troubles. With TSC, there's the clock skew between the two cores that they claim was fixed in SP2. (You could also sidestep this problem by setting core affinity to the same core for all your threads that were going to examine the time.) But there's another problem: the TSC frequency actually *does* change when SpeedStep kicks in. I know someone who complained bitterly about running Half-Life 2 on their shiny new laptop, and when it'd overheat SpeedStep would knock down the processor speed and the game's logic update rate would drop in half and now Gordon was running through molasses. With the ACPI timer, that's where you saw the leap-forwards-by-several-seconds-under-heavy-load problem (the cited MSKB article KB274323). That only happened with a specific south bridge chipset, which was Pentium-III-only. I never heard about anyone experiencing that problem--personally I had good experiences with that timer. The downside of the ACPI timer is that it's slow to read; it took just over a microsecond in my experiments. (timeGetTime was 20x faster. I don't know how long GetTickCount takes.) The documentation warnings about timeBeginPeriod is ancient, like Windows 95 era. On any computer running Python 3.3, you can safely call timeBeginPeriod(1) with confidence that you'll get consistent 1ms resolution. Likewise with calling into winmm--it shipped with every OS 3.3 supports. It's just not a big deal and you don't need to mention it in the PEP. I had a hypothetical idea for a hybrid software clock for games that would poll all possible sources of time (RDTSC, QPC, GetTickCount, timeGetTime) and do its level best to create a high-quality synthetic time. Like, if QPC jumped forward by a huge amount, and that jump wasn't corroborated by the other time functions, it'd throw that delta away completely. It'd also notice if QPC's frequency had changed due to SpeedStep and recalibrate. And it'd handle rollover of timeGetTime(). Of course, part of the problem is that calling all these clocks is slow. Another is that if QPC is implemented using RDTSC and RDTSC has problems you're kind of out of options--your best clock at that point only has 1ms accuracy. Anyway I never wound up getting this to work--my attempts were all full of nasty heuristics and the code turned into hash. Maybe someone smarter than me could figure out how to get it to work. Sorry that this is incomplete / dashed off, but I'm still on vacation and it's been a few years since I did Windows timing stuff. And I gotta go to bed--going to Madurodam in the morning! //arry/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
FYI, Victor, the PEP is slightly incomplete. Sure. What should be added to the PEP? But there's another problem: the TSC frequency actually *does* change when SpeedStep kicks in. I know someone who complained bitterly about running Half-Life 2 on their shiny new laptop, and when it'd overheat SpeedStep would knock down the processor speed and the game's logic update rate would drop in half and now Gordon was running through molasses. Yes, I already changed the PEP to not use QPC anymore for time.monotonic() because it has too many issues. I didn't mention the CPU frequency change issue in the PEP because I failed to find recent information about this issue. Is it an old bug or does it still occur with Windows Vista or Seven? Does Windows Vista and Seven still use TSC or they prefer other hardware clocks like ACPI PMT or HPET? Last info that I found: Historically, the TSC increased with every internal processor clock cycle, but now the rate is usually constant (even if the processor changes frequency) and usually equals the maximum processor frequency. The instructor RDTSC can be used to read this counter. The documentation warnings about timeBeginPeriod is ancient, like Windows 95 era. Which warning? The power consumption issue mentioned in the PEP? Likewise with calling into winmm--it shipped with every OS 3.3 supports. It's just not a big deal and you don't need to mention it in the PEP. I mentioned that the function requires the winmm library because a static or dynamic link to a library can be an issue. Especially if we use this function in Python core. clock_gettime(CLOCK_REALTIME) is not used on Linux for _PyTime_gettimeofday() because it requires to link Python to the rt (real-time) library, but it is used by time.time() (I changed it recently). Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
If we provide a way to check if the monotonic clock is monotonic (or not), I agree to drop the flag from time.monotonic(fallback=True) and always fallback. I was never a fan of the truly monotonic clock. time.clock_info('monotonic')['is_monotonic'] is a good candidate to store this information. I updated the PEP to add time.get_clock_info() and to drop the fallback parameter of time.monotonic() (which now always falls back). Because monotonic word cannot define time.monotonic() anymore, I suggest to rename the time.monotonic() function to time.steady(). So we would have: - time.steady() may or may not be monotonic, but its is as steady as possible. - time.get_clock_info('steady')['is_monotonic'] which looks less surprising than time.get_clock_info('monotonic')['is_monotonic'] It doesn't follow the C++ steady_clock definition, but it looks like the Boost library doesn't follow the C++ definition... (it uses CLOCK_MONOTONIC on Linux) By the way, it now prefer to use CLOCK_MONOTONIC instead of CLOCK_MONOTONIC_RAW on Linux. It is what I need in practice. If the hardware clock is a little bit too fast or too slow, NTP adjusts its rate so a delta of two timestamps is really a number of seconds. It's not yet written explicitly in the PEP, but the unit of time.monotonic/time.steady and time.highres is a second. Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Sat, Mar 31, 2012 at 7:37 PM, Victor Stinner victor.stin...@gmail.com wrote: If we provide a way to check if the monotonic clock is monotonic (or not), I agree to drop the flag from time.monotonic(fallback=True) and always fallback. I was never a fan of the truly monotonic clock. time.clock_info('monotonic')['is_monotonic'] is a good candidate to store this information. I updated the PEP to add time.get_clock_info() and to drop the fallback parameter of time.monotonic() (which now always falls back). Because monotonic word cannot define time.monotonic() anymore, I suggest to rename the time.monotonic() function to time.steady(). So we would have: - time.steady() may or may not be monotonic, but its is as steady as possible. - time.get_clock_info('steady')['is_monotonic'] which looks less surprising than time.get_clock_info('monotonic')['is_monotonic'] It doesn't follow the C++ steady_clock definition, but it looks like the Boost library doesn't follow the C++ definition... (it uses CLOCK_MONOTONIC on Linux) By the way, it now prefer to use CLOCK_MONOTONIC instead of CLOCK_MONOTONIC_RAW on Linux. It is what I need in practice. If the hardware clock is a little bit too fast or too slow, NTP adjusts its rate so a delta of two timestamps is really a number of seconds. It's not yet written explicitly in the PEP, but the unit of time.monotonic/time.steady and time.highres is a second. Hmm... I believe NTP can also slew the clock to deal with leap seconds (which the POSIX standard requires must be ignored). That is, when a leap second is inserted, the clock is supposed to stop value for one second. What actually happens is that for some time around the leap second (I've heard maybe a day), the clock is slowed down slightly. I'm guessing that this affects CLOCK_MONOTONIC but not CLOCK_MONOTONIC_RAW. Personally I'd rather use the latter -- if I want to be synchronous with wall clock time, I can just use time.time(). -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 1:21 PM, Victor Stinner victor.stin...@gmail.com wrote: Windows provides two main monotonic clocks: QueryPerformanceCounter() and GetTickCount(). QueryPerformanceCounter() has a good accuracy (0.3 ns - 5 ns) but has various issues and is know to not have a steady rate. GetTickCount() has a worse accuracy (1 ms - 15 ms) but is more stable and behave better on system suspend/resume. The glib library prefers GetTickCount() over QueryPerformanceCounter() for its g_get_monotonic_time() because The QPC timer has too many issues to be used as is. Ihttp://mail.gnome.org/archives/commits-list/2011-November/msg04589.html The Qt library tries QueryPerformanceCounter() but may fallback to GetTickCount() if it is not available. python-monotonic-time only uses GetTickCount() or GetTickCount64(). It is important to decide which clock is used for the Python time.monotonic() because it may change the design of the PEP 418. If we use GetTickCount() for time.monotonic(), we should use QueryPerformanceCounter() for time.highres(). But in this case, it means that time.highres() is not a simple try monotonic or falls back to system time, but may use a different clock with an higher resolution. So we might add a third function for the try monotonic or falls back to system time requirement. Python implements time.clock() using QueryPerformanceCounter() on Windows. Oh dear. I really want to say that 15 ms is good enough. Some possible exceptions I can think of: - Profiling. But this really wants to measure CPU time anyways, and it already uses a variety of hacks and heuristics to pick the best timer, so I don't really care. - Certain algorithms for thread (or even process?) communication might benefit from being able to set very short timeouts. But it seems you can just specify a timeout when waiting for a lock and it will be taken care of. So probably a non-use-case. So I think I still prefer GetTickCount*() over QueryPerformanceCounter(). And this is another reason why I don't like highres as a name -- as I said, I really prefer to have just two new functions, one that's a decent OS-provided timer that isn't affected by wall clock adjustments, if there is one, and the other strictly an alias for that one with a fallback to time.time() if there isn't one. Having two different OS-provided timers with different pros and cons will just make it too hard for users to decide, and hence we'll see a higher rate of using the wrong timer. (In fact, this even argues against having both the timer with fallback and the timer without fallback. So maybe we should just have a single timer function, *with* fallback, and a separate mechanism to inquire its properties.) -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 1:52 PM, Guido van Rossum gu...@python.org wrote: On Fri, Mar 30, 2012 at 1:21 PM, Victor Stinner victor.stin...@gmail.com wrote: Windows provides two main monotonic clocks: QueryPerformanceCounter() and GetTickCount(). QueryPerformanceCounter() has a good accuracy (0.3 ns - 5 ns) but has various issues and is know to not have a steady rate. GetTickCount() has a worse accuracy (1 ms - 15 ms) but is more stable and behave better on system suspend/resume. The glib library prefers GetTickCount() over QueryPerformanceCounter() for its g_get_monotonic_time() because The QPC timer has too many issues to be used as is. Ihttp://mail.gnome.org/archives/commits-list/2011-November/msg04589.html The Qt library tries QueryPerformanceCounter() but may fallback to GetTickCount() if it is not available. python-monotonic-time only uses GetTickCount() or GetTickCount64(). It is important to decide which clock is used for the Python time.monotonic() because it may change the design of the PEP 418. If we use GetTickCount() for time.monotonic(), we should use QueryPerformanceCounter() for time.highres(). But in this case, it means that time.highres() is not a simple try monotonic or falls back to system time, but may use a different clock with an higher resolution. So we might add a third function for the try monotonic or falls back to system time requirement. Python implements time.clock() using QueryPerformanceCounter() on Windows. Oh dear. I really want to say that 15 ms is good enough. Some possible exceptions I can think of: - Profiling. But this really wants to measure CPU time anyways, and it already uses a variety of hacks and heuristics to pick the best timer, so I don't really care. - Certain algorithms for thread (or even process?) communication might benefit from being able to set very short timeouts. But it seems you can just specify a timeout when waiting for a lock and it will be taken care of. So probably a non-use-case. So I think I still prefer GetTickCount*() over QueryPerformanceCounter(). And this is another reason why I don't like highres as a name -- as I said, I really prefer to have just two new functions, one that's a decent OS-provided timer that isn't affected by wall clock adjustments, if there is one, and the other strictly an alias for that one with a fallback to time.time() if there isn't one. Having two different OS-provided timers with different pros and cons will just make it too hard for users to decide, and hence we'll see a higher rate of using the wrong timer. (In fact, this even argues against having both the timer with fallback and the timer without fallback. So maybe we should just have a single timer function, *with* fallback, and a separate mechanism to inquire its properties.) And disagreeing with myself, I just found myself using a tool for RPC analytics that displays times in msec, and the times are often between 1 and 20 msec. Here a 15 msec timer would be horrible, and I see no alternative but to use QPC()... (Well, if the tool ran on Windows, which it doesn't. :-) Can we tell what the accuracy of GetTickCount*() is when we first request the time, and decode then? Can you go into more detail about QPC()'s issues? What is unsteady about its rate? -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Possibly we really do need two timers, one for measuring short intervals and one for measuring long intervals? Perhaps we can use this to decide on the names? Anyway, the more I think about it, the more I believe these functions should have very loose guarantees, and instead just cater to common use cases -- availability of a timer with minimal fuss is usually more important than the guarantees. So forget the idea about one version that falls back to time.time() and another that doesn't -- just always fall back to time.time(), which is (almost) always better than failing. Then we can design a separate inquiry API (doesn't have to be complex as long as it's extensible -- a dict or object with a few predefined keys or attributes sounds good enough) for apps that want to know more about how the timer they're using is actually implemented. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On 30Mar2012 13:52, Guido van Rossum gu...@python.org wrote: | (In fact, this even argues against having both the timer with fallback | and the timer without fallback. So maybe we should just have a single | timer function, *with* fallback, and a separate mechanism to inquire | its properties.) Well, you should be able to know what kind of clock you're getting. But what do to if you don't get a satisfactory one? There's then no way for ask for an alternative; you don't get to control the fallback method, for example. I've come to the opinion that the chosen approach is wrong, and suggest a better one. There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution - no steps and only a few, fortunately. I think you're doing this wrong at the API level. People currently are expecting to call (for example) time.monotonic() (or whatever) and get back now, a hopefully high resolution float. Given the subtlety sought for various purposes, people should be calling: T = time.getclock(flags) and then later calling: T.now() to get their float. That way people can: - request a set of the three characteristics above - inspect what they get back (it should have all the requested flags, but unrequested flags may be set or not depending on the underlying facility) Obviously this should return None or raise an exception if the flag set can't be met. Then users can request a less featured clock on failure, depending on what aspects of the clock are most desirable to their use case. Or of course fail if fallback is not satisfactory. Of course you can provide some convenient-with-fallback function that will let people do this in one hit without the need for T, but it should not be the base facility offered. The base should let people request their feature set and inspect what is supplied. Cheers, -- Cameron Simpson c...@zip.com.au DoD#743 http://www.cskk.ezoshosting.com/cs/ Time is nature's way of keeping everything from happening at once. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 2:43 PM, Cameron Simpson c...@zip.com.au wrote: On 30Mar2012 13:52, Guido van Rossum gu...@python.org wrote: | (In fact, this even argues against having both the timer with fallback | and the timer without fallback. So maybe we should just have a single | timer function, *with* fallback, and a separate mechanism to inquire | its properties.) Well, you should be able to know what kind of clock you're getting. But what do to if you don't get a satisfactory one? There's then no way for ask for an alternative; you don't get to control the fallback method, for example. I've come to the opinion that the chosen approach is wrong, and suggest a better one. There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution - no steps and only a few, fortunately. I think you're doing this wrong at the API level. People currently are expecting to call (for example) time.monotonic() (or whatever) and get back now, a hopefully high resolution float. Given the subtlety sought for various purposes, people should be calling: T = time.getclock(flags) and then later calling: T.now() to get their float. That way people can: - request a set of the three characteristics above - inspect what they get back (it should have all the requested flags, but unrequested flags may be set or not depending on the underlying facility) Obviously this should return None or raise an exception if the flag set can't be met. Then users can request a less featured clock on failure, depending on what aspects of the clock are most desirable to their use case. Or of course fail if fallback is not satisfactory. Of course you can provide some convenient-with-fallback function that will let people do this in one hit without the need for T, but it should not be the base facility offered. The base should let people request their feature set and inspect what is supplied. I like this out-of-the-box thinking. But I'm still wondering if there really are enough flags for this to be worth it. If there are, great, the API is pretty. But if there are only 2 or 3 flag combinations that make actual sense, let's forget it. Another out-of-the-box idea, going back to simplicity: have just one new function, time.hrtimer(), which is implemented using the highest-resolution timer available on the platform, but with no strong guarantees. It *may* jump, move back, drift, change its rate, or roll over occasionally. We try to use the implementation that's got the fewest problems, but we don't try to hide its deficiencies, and nothing suitable exists, it may be equivalent to time.time(). If the times you measure are too weird, measure again. For scheduling things a day or more in the future, you should use time.time() instead. One issue that hasn't had enough attention: *scope* of a timer. If two processes running on the same machine ask for the time, do the values they see use the same epoch, or is the epoch dependent on the process? Some code I saw in timemodule.c for working around Windows clocks rolling over seem to imply that two processes may not always see the same timer value. Is there a use case where this matters? -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Can you go into more detail about QPC()'s issues? Yes, see the PEP: http://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter What is unsteady about its rate? Hum, I read that you can expect a drift between QPC and GetTickCount. I don't have exact numbers. There are also issues with power-saving. When the CPU frequency changes, the frequency of the TSC is also impacted on some processors (others provide a TSC at a fixed frequency). 2012/3/30 Guido van Rossum gu...@python.org: Possibly we really do need two timers, one for measuring short intervals and one for measuring long intervals? Perhaps we can use this to decide on the names? short and long interval is not how these clocks should be defined. I prefer use cases: * time.highres() should be used for profiling and benchmarking * time.monotonic() should be used for a scheduler and timeout time.monotonic() rate should be as steady as possible, its stability is more important than its accuracy. time.highres() should provide the clock with the best accuracy. Both clocks may have an undefined starting point. Anyway, the more I think about it, the more I believe these functions should have very loose guarantees, and instead just cater to common use cases -- availability of a timer with minimal fuss is usually more important than the guarantees. So forget the idea about one version that falls back to time.time() and another that doesn't -- just always fall back to time.time(), which is (almost) always better than failing. I disagree. Python must provide a truly monotonic clock, even it is not truly monotonic by default. If we want to provide a convinient monotonic or falllback to system time, there are different options: add a dedicated function (e.g. time.try_monotonic()) or add a parameter to enable or disable the fallback. Between these two options, I prefer the parameter because it avoids the creation of a new function. Even if I now agree that a truly monotonic clock is required, I also agree with Guido: the most common case is to use a fallback. I suggest this API: time.monotonic(fallback=True). Another option is to not provide a monotonic or falllback to system time clock and write an explicit try/except where you need a fallback. I don't like this solution because time.monotonic() might fail at runtime with OSError, and so catching AttributeError is not enough... Then we can design a separate inquiry API (doesn't have to be complex as long as it's extensible -- a dict or object with a few predefined keys or attributes sounds good enough) for apps that want to know more about how the timer they're using is actually implemented. Sometimes, it does matter which exact OS clock is used. The QElapsedTime class of the Qt libraries has an attribute (an enum) describing which clock is used. We can give the name of the function and the resolution. In some specific cases, we are able to read the accuracy (ex: GetTickCount). The accuracy may change at runtime (at least for GetTickCount). Should I include such new function in the PEP, or can it be discussed (later) in a separated thread? -- I don't want to only provide time.monotonic() which would fallback if no monotonic clock is available, because we would be unable to tell if the clock is monotonic or not. See the implementation in the PEP: the try monotonic or fallback function may use a different clock at each call, and so may be monotonic at startup and then becomes non-monotonic. An alternative is time.monotonic() returning (time, is_monotonic) but this is an ugly API. You cannot simply write: a=time.monotonic(); benchmark(); b=time.monotonic(); print(b-a) because it raises a TypeError on b-a. -- I will update the PEP to describe my new proposition. Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On 30Mar2012 15:21, Guido van Rossum gu...@python.org wrote: | On Fri, Mar 30, 2012 at 2:43 PM, Cameron Simpson c...@zip.com.au wrote: | Given the subtlety sought for various purposes, people should be | calling: | T = time.getclock(flags) | and then later calling: | T.now() | to get their float. | | That way people can: | - request a set of the three characteristics above | - inspect what they get back (it should have all the requested flags, | but unrequested flags may be set or not depending on the underlying | facility) | Obviously this should return None or raise an exception if the flag | set can't be met. | | Then users can request a less featured clock on failure, depending on | what aspects of the clock are most desirable to their use case. Or of | course fail if fallback is not satisfactory. [...] | I like this out-of-the-box thinking. But I'm still wondering if there | really are enough flags for this to be worth it. If there are, great, | the API is pretty. But if there are only 2 or 3 flag combinations that | make actual sense, let's forget it. There are at least three characteristics listed above. There are several use cases described in the long discussions. I don't think we should be saying we will only support these 3 thought-of use cases and the others are too hard/weird/perverse/rare. We should be saying: we can characterise clocks in these very few ways. Ask for a clock of some kind. We will provide one (abitrarily, though perhaps preferring higher precision) that satisfies the request if available. I can easily envisage calling code as simple as this: T = getclock(T_MONOTONIC|T_HIGHRES) or getclock(T_MONOTONIC) to do my own fallback for my own use case if we went with returning None if there is no satisfactory clock. If I need monotonic (for example) my code is in NO WAY helped by being handed something that sometimes is not monotonic; to make my code reliable I would need to act as though I wasn't getting a montonic clock in the first place. No win there at all. This has the following advantages: - it removes _all_ policy from the PEP, at least at the core - it makes things totally clear and concise at the calling end; the clock characterists are right there in front of the reader - policy is in the hands of the user where it belongs, and is easy to specify into the bargain - it avoids the horrendous ideas mooted of asking for something called monotonic and getting sometime only mostly monotonic, and the equivalent flavours for the other flags - implementation of the PEP is in principle as easy as a table of clock wrappers with the flags each supports. Loop over the table until one matches all the requested flags, or return None. - for higher quality of implementation you embed policy in the convenience function, not the getclock() function To take your suggestion of: Another out-of-the-box idea, going back to simplicity: have just one new function, time.hrtimer(), which is implemented using the highest-resolution timer available on the platform, but with no strong guarantees. Example: T = time.hrtimer() which would provide the best hires timer. You'd give it an optional flag argument for additional flags so that you could request the most-hires timer matching the flags. This is like: T = time.getclock(T_HIRES) except that is makes clear your preferred attribute. So internally one would have: - clock wrappers for the platform specific facilities, with the constructors being singletons or not as suits the facility - a list of the wrappers with their flag sets specifiying what clock attributes they offer - for the .hrtimer([flags]) or .monotonic([flags]) calls they each have their own list of the clock wrapper, ordered on most-hires or best-monotonic, as the implementor sees fit That gets you: - arbitrary user case support - convenience functions for common policies | It *may* jump, move back, drift, change its rate, or roll | over occasionally. We try to use the implementation that's got the | fewest problems, but we don't try to hide its deficiencies, and | nothing suitable exists, it may be equivalent to time.time(). If the | times you measure are too weird, measure again. For scheduling things | a day or more in the future, you should use time.time() instead. Getting ugly. This is why I think we should not be offering only what we think the user may want, especially when we offer something loose and rubbery like this. Instead, get the user to ask. The platform timers can all be well characterised with respect to the flags suggested above; you only need to tabulate what timers offer what behaviours. By all means offer convenience functions providing common choices, but don't make those the _only_ choices. Let the user ask for anything; if the platform can't support it that's a pity, but leave the user
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Given the amount of disagreement I sense, I think we'll need to wait for more people to chime in. On Fri, Mar 30, 2012 at 3:47 PM, Victor Stinner victor.stin...@gmail.com wrote: Can you go into more detail about QPC()'s issues? Yes, see the PEP: http://www.python.org/dev/peps/pep-0418/#windows-queryperformancecounter What is unsteady about its rate? Hum, I read that you can expect a drift between QPC and GetTickCount. I don't have exact numbers. There are also issues with power-saving. When the CPU frequency changes, the frequency of the TSC is also impacted on some processors (others provide a TSC at a fixed frequency). And how does that impact teh various use cases? (There still isn't enough about use cases in the PEP. Thank you very much though for adding all those details about the various platform clocks.) 2012/3/30 Guido van Rossum gu...@python.org: Possibly we really do need two timers, one for measuring short intervals and one for measuring long intervals? Perhaps we can use this to decide on the names? short and long interval is not how these clocks should be defined. Why not? I prefer use cases: * time.highres() should be used for profiling and benchmarking * time.monotonic() should be used for a scheduler and timeout So if I want to schedule something a week in the future, what should I use? monotonic() or time()? And can you explain the reason for your answer? What about an hour or a day? Or a month or a year? time.monotonic() rate should be as steady as possible, its stability is more important than its accuracy. time.highres() should provide the clock with the best accuracy. Both clocks may have an undefined starting point. So what kind of drift is acceptable for each? Anyway, the more I think about it, the more I believe these functions should have very loose guarantees, and instead just cater to common use cases -- availability of a timer with minimal fuss is usually more important than the guarantees. So forget the idea about one version that falls back to time.time() and another that doesn't -- just always fall back to time.time(), which is (almost) always better than failing. I disagree. Python must provide a truly monotonic clock, even it is not truly monotonic by default. Why? If we want to provide a convenient monotonic or falllback to system time, there are different options: add a dedicated function (e.g. time.try_monotonic()) or add a parameter to enable or disable the fallback. Between these two options, I prefer the parameter because it avoids the creation of a new function. Even if I now agree that a truly monotonic clock is required, I also agree with Guido: the most common case is to use a fallback. I suggest this API: time.monotonic(fallback=True). But this goes against the idea of A keyword argument that gets passed as a constant in the caller is usually poor API. And it would encourage the creation of trivial lambdas just to call the timer with this flag, since a universal API is a timer function that takes no arguments. Another option is to not provide a monotonic or falllback to system time clock and write an explicit try/except where you need a fallback. I don't like this solution because time.monotonic() might fail at runtime with OSError, and so catching AttributeError is not enough... Check out Cameron Simpson's proposal earlier in this thread. If we really are going to have a variety of functions and fallback options, his approach may be the best. Then we can design a separate inquiry API (doesn't have to be complex as long as it's extensible -- a dict or object with a few predefined keys or attributes sounds good enough) for apps that want to know more about how the timer they're using is actually implemented. Sometimes, it does matter which exact OS clock is used. When is that? The QElapsedTime class of the Qt libraries has an attribute (an enum) describing which clock is used. We can give the name of the function and the resolution. In some specific cases, we are able to read the accuracy (ex: GetTickCount). The accuracy may change at runtime (at least for GetTickCount). That sounds like a fine API. Should I include such new function in the PEP, or can it be discussed (later) in a separated thread? FWIW, I prefer a single thread devoted to all aspects of this PEP. -- I don't want to only provide time.monotonic() which would fallback if no monotonic clock is available, because we would be unable to tell if the clock is monotonic or not. There could be a separate inquiry API. See the implementation in the PEP: the try monotonic or fallback function may use a different clock at each call, and so may be monotonic at startup and then becomes non-monotonic. No, it should never switch implementations once it has chosen. That's just asking for trouble. If it can become non-monotonic it just isn't monotonic. Again, Cameron Simpson's idea might help here. An alternative is
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 4:44 PM, Cameron Simpson c...@zip.com.au wrote: [Lots of good stuff] Maybe you and Victor should try to merge your proposals off-line and then get back with a new proposal here. Make the epoch available in the clock wrapper as a property. At least then there's a mechanism for reconciling things. Don't try to mandate something that possibly can't be mandated. Ah, but if a clock drifts, the epoch may too -- and we may never know it. I like knowing all sorts of things about a clock, but I'm not sure that for clocks other than time.time() I'd ever want to know the epoch -- ISTM that the only thing I could do with that information would be shooting myself in the foot. If you really want the epoch, compute it yourself by bracketing a timer() call in two time() calls, or vice versa (not sure which is better :-). -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
2012/3/31 Guido van Rossum gu...@python.org: Given the amount of disagreement I sense, I think we'll need to wait for more people to chime in. I hope that the PEP now gives enough data to help to choose the best API. Hum, I read that you can expect a drift between QPC and GetTickCount. I don't have exact numbers. There are also issues with power-saving. When the CPU frequency changes, the frequency of the TSC is also impacted on some processors (others provide a TSC at a fixed frequency). And how does that impact teh various use cases? (There still isn't enough about use cases in the PEP. Thank you very much though for adding all those details about the various platform clocks.) I didn't find a good source, but it looks like QueryPerformanceCounter behaves badly on system suspend/resume, whereas GetTickCount is reliable and has a well defined behaviour: The elapsed time retrieved by GetTickCount or GetTickCount64 includes time the system spends in sleep or hibernation. So QPC is not really monotonic nor steady. It may be even worse than the system clock (especially in virtual machines). Impact: A timeout may be 42 seconds shorter than the requested duration if is uses QPC. For a scheduler, a task would be scheduled at the right moment. I prefer use cases: * time.highres() should be used for profiling and benchmarking * time.monotonic() should be used for a scheduler and timeout So if I want to schedule something a week in the future, what should I use? monotonic() or time()? And can you explain the reason for your answer? What about an hour or a day? Or a month or a year? You should use time.monotonic() because time.monotonic() has a steady rate and so is reliable for long duration (at least more reliable than time.highres()). In practice, time.monotonic() and time.highres() are only different on Windows. If I understood correctly, the Windows kernel uses something like GetTickCount whch has an accuracy of 1 ms in the best case. So Python only needs a clock with a similar accuracy for timeout and schedulers. time.highres() (QPC) rate is only steady during a short duration: it is not an issue for a benchmark because you usually rerun the same test at least 3 times and keep the minimum. It looks like QPC bugs are only unexpected forward jumps (no backward jump), so taking the minimum would workaround these issues. The hibernation issue should not affect benchmarking/profiling. time.monotonic() rate should be as steady as possible, its stability is more important than its accuracy. time.highres() should provide the clock with the best accuracy. Both clocks may have an undefined starting point. So what kind of drift is acceptable for each? I don't know. I disagree. Python must provide a truly monotonic clock, even it is not truly monotonic by default. Why? See Zooko Wilcox-O'Hearn's email: http://mail.python.org/pipermail/python-dev/2012-March/118147.html I suggest this API: time.monotonic(fallback=True). But this goes against the idea of A keyword argument that gets passed as a constant in the caller is usually poor API. Right :-) After changing (again) the PEP, I realized that it reintroduces the time.monotonic(fallback=False) raising NotImplementedError case and I really don't like this exception here. And it would encourage the creation of trivial lambdas just to call the timer with this flag, since a universal API is a timer function that takes no arguments. My bet is that fallback=True is an uncommon use case. Sometimes, it does matter which exact OS clock is used. When is that? If you need to know more properties of the clock,. For example, Python may be unable to give the accuracy of the clock, but you may get it differently if you know which clock function is used. Should I include such new function in the PEP, or can it be discussed (later) in a separated thread? FWIW, I prefer a single thread devoted to all aspects of this PEP. Let's propose an API: time.clock_info() - {'time': {'function': 'gettimeofday', 'resolution': 1e-6, 'monotonic': False}, 'monotonic': {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True}, 'highres': {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True}} or time.clock_info('time') - {'function': 'gettimeofday', 'resolution': 1e-6, 'monotonic': False} time.clock_info('monotonic') - {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True} time.clock_info( 'highres') - {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True} or time.clock_info(time.time) - {'function': 'gettimeofday', 'resolution': 1e-6, 'monotonic': False} time.clock_info(time.monotonic) - {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True} time.clock_info( time.highres) - {'function': 'clock_gettime(CLOCK_MONOTONIC)', 'resolution': 1e-9, 'monotonic': True} clock_ prefix in
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Mar 30, 2012, at 8:51 PM, Victor Stinner wrote: time.highres() (QPC) rate is only steady during a short duration QPC is not even necessarily steady for a short duration, due to BIOS bugs, unless the code running your timer is bound to a single CPU core. http://msdn.microsoft.com/en-us/library/ms644904 mentions SetThreadAffinityMask for this reason, despite the fact that it is usually steady for longer than that. -glyph ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution These features look to be exclusive on Windows. On other platforms, it looks like monotonic clocks are always the most accurate clocks. So I don't think that we need to be able to combine these two flags. - no steps You mean not adjusted by NTP? Except CLOCK_MONOTONIC on Linux, no monotonic clock is adjusted by NTP. On Linux, there is CLOCK_MONOTONIC_RAW, but it is only available on recent Linux kernel (2.6.28). Do you think that it is important to be able to refuse a monotonic clock adjusted by NTP? What would be the use case of such truly steady clock? -- The PEP 418 tries to expose various monotonic clocks in Python with a simple API. If we fail to agree how to expose these clocks, e.g. because there are major differences between these clocks, another solution is to only expose low-level function. This is already what we do with the os module, and there is the shutil module (and others) for a higher level API. I already added new low-level functions to the time module: time.clock_gettime() and time.clock_getres(). Of course you can provide some convenient-with-fallback function that will let people do this in one hit without the need for T, but it should not be the base facility offered. The base should let people request their feature set and inspect what is supplied. The purpose of such function is to fix programs written with Python 3.3 and using time.time() whereas a monotonic would be the right clock (e.g. implement a timeout). Another concern is to write portable code. Python should help developers to write portable code, and time.monotonic(fallback=False) is not always available (and may fail). Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 5:51 PM, Victor Stinner victor.stin...@gmail.com wrote: 2012/3/31 Guido van Rossum gu...@python.org: Given the amount of disagreement I sense, I think we'll need to wait for more people to chime in. I hope that the PEP now gives enough data to help to choose the best API. Lots of data, but not enough motivation, not enough about the use cases. Hum, I read that you can expect a drift between QPC and GetTickCount. I don't have exact numbers. There are also issues with power-saving. When the CPU frequency changes, the frequency of the TSC is also impacted on some processors (others provide a TSC at a fixed frequency). And how does that impact teh various use cases? (There still isn't enough about use cases in the PEP. Thank you very much though for adding all those details about the various platform clocks.) I didn't find a good source, but it looks like QueryPerformanceCounter behaves badly on system suspend/resume, whereas GetTickCount is reliable and has a well defined behaviour: The elapsed time retrieved by GetTickCount or GetTickCount64 includes time the system spends in sleep or hibernation. So QPC is not really monotonic nor steady. It may be even worse than the system clock (especially in virtual machines). I think you are in serious danger of overspecifying the problem. No clock can fulfill all requirements. (That's why there are so many to choose from of course!) Impact: A timeout may be 42 seconds shorter than the requested duration if is uses QPC. For a scheduler, a task would be scheduled at the right moment. I don't understand this paragraph. And why is it always exactly a loss of 42 seconds? I prefer use cases: * time.highres() should be used for profiling and benchmarking * time.monotonic() should be used for a scheduler and timeout So if I want to schedule something a week in the future, what should I use? monotonic() or time()? And can you explain the reason for your answer? What about an hour or a day? Or a month or a year? You should use time.monotonic() because time.monotonic() has a steady rate and so is reliable for long duration (at least more reliable than time.highres()). Ah, but have you *thought* about the use case? *Why* would I want to schedule something that far in the future? Maybe it's a recurring birthday? Surely time() is better for that. (Etc. Think!) My question is trying to tease out the meaning of the various clocks that might exist. In practice, time.monotonic() and time.highres() are only different on Windows. If I understood correctly, the Windows kernel uses something like GetTickCount whch has an accuracy of 1 ms in the best case. So Python only needs a clock with a similar accuracy for timeout and schedulers. So is it worth having two functions that are only different on Windows? ISTM that the average non-Windows user will have a 50% chance of picking the wrong timer from a portability perspective. time.highres() (QPC) rate is only steady during a short duration: it is not an issue for a benchmark because you usually rerun the same test at least 3 times and keep the minimum. It looks like QPC bugs are only unexpected forward jumps (no backward jump), so taking the minimum would workaround these issues. The hibernation issue should not affect benchmarking/profiling. Now you're talking: indeed the application should work around the limitations (if there are any) using end-to-end means, since only the application developer knows what matters to them. time.monotonic() rate should be as steady as possible, its stability is more important than its accuracy. time.highres() should provide the clock with the best accuracy. Both clocks may have an undefined starting point. So what kind of drift is acceptable for each? I don't know. Ok, let's just assume that we can't control drift so we'll have to let the app deal with it. I disagree. Python must provide a truly monotonic clock, even it is not truly monotonic by default. Why? See Zooko Wilcox-O'Hearn's email: http://mail.python.org/pipermail/python-dev/2012-March/118147.html He explains the basic difference between the two types of clocks, and that's important. He doesn't say anything about a strict requirement for monotonicity or steadiness. This is why I still balk at monotonic for the name -- I don't think that monotonicity is the most important property. But I don't know how the put the desired requirement in words; steady seems to come closer for sure. I suggest this API: time.monotonic(fallback=True). But this goes against the idea of A keyword argument that gets passed as a constant in the caller is usually poor API. Right :-) After changing (again) the PEP, I realized that it reintroduces the time.monotonic(fallback=False) raising NotImplementedError case and I really don't like this exception here. Me neither. And it would encourage the creation of trivial lambdas just to call the timer with this
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Fri, Mar 30, 2012 at 6:24 PM, Victor Stinner victor.stin...@gmail.com wrote: There seem to be a few competing features for clocks that people want: - monotonic - never going backward at all - high resolution These features look to be exclusive on Windows. On other platforms, it looks like monotonic clocks are always the most accurate clocks. So I don't think that we need to be able to combine these two flags. - no steps You mean not adjusted by NTP? Except CLOCK_MONOTONIC on Linux, no monotonic clock is adjusted by NTP. On Linux, there is CLOCK_MONOTONIC_RAW, but it is only available on recent Linux kernel (2.6.28). Do you think that it is important to be able to refuse a monotonic clock adjusted by NTP? What would be the use case of such truly steady clock? That depends on what NTP can do to the clock. If NTP makes the clock tick *slightly* faster or slower in order to gradually adjust the wall clock, that's fine. If NTP can make it jump wildly forward or even backward, it's no better than time.time(), and we know why (for some purposes) we don't want that. -- The PEP 418 tries to expose various monotonic clocks in Python with a simple API. If we fail to agree how to expose these clocks, e.g. because there are major differences between these clocks, another solution is to only expose low-level function. This is already what we do with the os module, and there is the shutil module (and others) for a higher level API. I already added new low-level functions to the time module: time.clock_gettime() and time.clock_getres(). Of course you can provide some convenient-with-fallback function that will let people do this in one hit without the need for T, but it should not be the base facility offered. The base should let people request their feature set and inspect what is supplied. The purpose of such function is to fix programs written with Python 3.3 and using time.time() whereas a monotonic would be the right clock (e.g. implement a timeout). Another concern is to write portable code. Python should help developers to write portable code, and time.monotonic(fallback=False) is not always available (and may fail). -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Mar 30, 2012, at 9:32 PM, Guido van Rossum wrote: - no steps You mean not adjusted by NTP? Except CLOCK_MONOTONIC on Linux, no monotonic clock is adjusted by NTP. On Linux, there is CLOCK_MONOTONIC_RAW, but it is only available on recent Linux kernel (2.6.28). Do you think that it is important to be able to refuse a monotonic clock adjusted by NTP? What would be the use case of such truly steady clock? That depends on what NTP can do to the clock. If NTP makes the clock tick *slightly* faster or slower in order to gradually adjust the wall clock, that's fine. If NTP can make it jump wildly forward or even backward, it's no better than time.time(), and we know why (for some purposes) we don't want that. no steps means something very specific. It does not mean not adjusted by NTP. In NTP, changing the clock frequency to be slightly faster or slower is called slewing (which is done with adjtime()). Jumping by a large amount in a single discrete step is called stepping (which is done with settimeofday()). This is sort-of explained by http://doc.ntp.org/4.1.2/ntpd.htm. I think I'm agreeing with Guido here when I say that, personally, my understanding is that slewing is generally desirable (i.e. we should use CLOCK_MONOTONIC, not CLOCK_MONOTONIC_RAW) if one wishes to measure real time (and not a time-like object like CPU cycles). This is because the clock on the other end of the NTP connection from you is probably better at keeping time: hopefully that thirty five thousand dollars of Cesium timekeeping goodness is doing something better than your PC's $3 quartz crystal, after all. So, slew tends to correct for minor defects in your local timekeeping mechanism, and will compensate for its tendency to go too fast or too slow. By contrast, stepping only happens if your local clock is just set incorrectly and the re-sync delta has more to do with administrative error or failed batteries than differences in timekeeping accuracy. -glyph ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
Impact: A timeout may be 42 seconds shorter than the requested duration if is uses QPC. For a scheduler, a task would be scheduled at the right moment. I don't understand this paragraph. And why is it always exactly a loss of 42 seconds? Sorry, it's late here, I'm too tired. A jump of 42 seconds is one of QPC known bug (it was a bug in VirtualBox and it is now fixed). So is it worth having two functions that are only different on Windows? ISTM that the average non-Windows user will have a 50% chance of picking the wrong timer from a portability perspective. Can we solve this by documenting correctly time.highres() issues (it's not really monotonic) and when you need to use time.monotonic() or time.highres()? Well, there is already time.clock() that uses QPC on Windows, but time.highres() and time.clock() give different results for an idle process on UNIX. pybench, timeit and other programs have their own heuristic getting the most accurate clock depending on the OS and on which clocks are available. time.highres() is a portable function for these programs. See Zooko Wilcox-O'Hearn's email: http://mail.python.org/pipermail/python-dev/2012-March/118147.html He explains the basic difference between the two types of clocks, and that's important. He doesn't say anything about a strict requirement for monotonicity or steadiness. This is why I still balk at monotonic for the name -- I don't think that monotonicity is the most important property. But I don't know how the put the desired requirement in words; steady seems to come closer for sure. If we provide a way to check if the monotonic clock is monotonic (or not), I agree to drop the flag from time.monotonic(fallback=True) and always fallback. I was never a fan of the truly monotonic clock. time.clock_info('monotonic')['is_monotonic'] is a good candidate to store this information. time.clock_info('monotonic')['is_monotonic'] looks like a bug: why would I check if a *monotonic* clock is *monotonic*? time.clock_info('steady')['monotonic'] looks more natural, but I don't remember why we should not use the term steady. Well, the PEP mentions something like that in the One function, no flag section. But you don't seem to like it. (In general the alternatives section could do with reasons for rejection or at least pros and cons for each alternative.) I was concerned by the fact that time.monotonic() may become not-monotonic between two calls, but I changed my mind. I agree that it should not occur in practice. So always fallback and add a way to know if the monotonic clock is monotonic now sounds like the best API to me. Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
(...) By contrast, stepping only happens if your local clock is just set incorrectly and the re-sync delta has more to do with administrative error or failed batteries than differences in timekeeping accuracy. Are you talking about CLOCK_REALTIME or CLOCK_MONOTONIC? Victor ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Mar 30, 2012, at 10:17 PM, Victor Stinner wrote: (...) By contrast, stepping only happens if your local clock is just set incorrectly and the re-sync delta has more to do with administrative error or failed batteries than differences in timekeeping accuracy. Are you talking about CLOCK_REALTIME or CLOCK_MONOTONIC? My understanding is: CLOCK_REALTIME is both stepped and slewed. CLOCK_MONOTONIC is slewed, but not stepped. CLOCK_MONOTONIC_RAW is neither slewed nor stepped. -glyph ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Use QueryPerformanceCounter() for time.monotonic() and/or time.highres()?
On Mar 30, 2012, at 10:25 PM, Glyph wrote: On Mar 30, 2012, at 10:17 PM, Victor Stinner wrote: (...) By contrast, stepping only happens if your local clock is just set incorrectly and the re-sync delta has more to do with administrative error or failed batteries than differences in timekeeping accuracy. Are you talking about CLOCK_REALTIME or CLOCK_MONOTONIC? My understanding is: CLOCK_REALTIME is both stepped and slewed. CLOCK_MONOTONIC is slewed, but not stepped. CLOCK_MONOTONIC_RAW is neither slewed nor stepped. Sorry, I realize I should cite my source. This mailing list post talks about all three together: http://www.spinics.net/lists/linux-man/msg00973.html Although the documentation one can find by searching around the web is really bad. It looks like many of these time features were introduced, to Linux at least, with no documentation. -glyph ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com