Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Time::HiRes not that high on windows

by BrowserUk (Patriarch)
on Sep 08, 2003 at 22:12 UTC ( [id://289891]=note: print w/replies, xml ) Need Help??


in reply to Time::HiRes not that high on windows

A quick inspection of the Win32 implementation of Time::HiRes, HiRes.dll reveals that the Kernel32 API, GetLocalTime() is used. This retrieves the date/ time structure SystemTime from system clock. This is documented as having a 1 millisecond resolution. so your interpretation of the results from Time::HiRes::Time() function is correct.

That said, if you can demonstrate that the time on your system is accurate, in absolute terms, to less than a millisecond relative to one of the atomic clocks accessible via the internet, I'll start to be impressed. If only in the algorithm you use to demonstrate it:)

Also, can you actually open a new file and right some meaningful data to it in less than 1 millisecond? The best I achieved on my system (which is admittedly very old and slow) was between 3 and 4 milliseconds, and this was only performing a single write of 10 bytes. Your filenames constructed from timestamps with resolutions greater than 1 millisecond, aren't going to do you a great deal of good when creating and putting anything in those files is likely to take at least 1 millisecond and probably longer. Also, under windows any way, the schedulers 'quantum' period can vary between 20 ms and 120 ms depending upon the version. This is the (maximum) amount of time each thread gets the processor before being preempted in favour of another thread (or process). I'm not sure what the schedulers quantum period is for Linux, but it is probably somewhere within this same range. This means that if there are only say 2 other process running in the system, then it is quite possible that your process will not be eligible to run, and therefore will be unable to create your files for at least a quarter of a second each time around the robin, so this kind of makes a mockery of attempting to utilise such high accuracy in the absolute timestamping of files.

The time (sic) when such accuracy is a valid requirement is when measuring elapsed times. As mentioned above, Win32 has several mechanisms for performing elapse timing to a much higher resolution that with the system clock. One of these is the pair of calls tye mentioned, QueryPerformanceFrequency() and QueryPerformanceCounter(). The first of these determines the number of increments of the counter that occur each second. On my 233Mhz system this comes back as 1193182/s, which translates to a resolution of .838 µs (That funny char is mu, for microseconds, from where I look at it).

Given that this is accurate enough to determine that it takes perl 3.3 µs longer to assign a double-quoted variable to another than it does to assign if it isn't double quoted, it seems good enough:) (I'm not publishing a benchmark, it was a very crude test, but consistent enough to mention.)

So, one point of view is that the system does provide access to facilities to measure time to a much higher precision than the system clocks 1 millisecond resolution, but it would require some extra code within Time::HiRes to make it available.

But the second point is that it is dubious as to how much higher resolution you can effectively make use of, especially from within Perl, whatever OS you are running on.

Given that from the instant your perl code decides to request the "current" time, to the instant that the value returned from the system is available for use, the interpreter has to locate the glob that hold the address of the function Time::HiRes::time(), the perl stack frame is set up, the call is invoked, now your in the XS code. That then has to set up it's local environment, and eventually call the OS. The OS does it's own housekeeping and eventually it executes the Pentium+ op code rdtsc "Read Time Stamp Counter", which is the basis of the high resolution timers on Intel chips regardless of which OS is running.

At this point you have the counter, but now you have to return that value. It's currently stored in a register, so you copy it into the memory passed by the OS to hold it. then you unwind the stack and transition back from level 0 code to level 3 code. We're now back in the XS code. So we have to transfer the value from C code memory into a Perl variable. And unwind the XS stackframe and were back into the perl code. In all, the windup and unwinding of stacks and environments has probably taken several hundred machine code instructions. Even on the latest 4.something GHz processors, this is going to take at least a few 10s and probably hundreds of microseconds. So the timestamp we took, was taken quite a while (relatively speaking) after whatever logic in the Perl program decided it needed the timestamp. And the value of the timestamp is already tens or hundreds of microseconds out of date by the time it is returned to the Perl code. And that value can be increased to several milliseconds if perchance the scheduler has decided to preempt our code in the meantime.

The upshot is, regardless of what OS you are using, writing code that relies upon knowing the absolute time to a resolution of greater than 1 millisecond is fraught with problems. For that level of resolution, you need a real time OS and highly (hand) optimised assembler.

Higher than millisecond resolution is useful for elapsed time calculations, at least to the 10th and maybe even 10oth of a millisecond for comparative purposes, and this level of accuracy can be made available to Perl code under Win32. That Time::HiRes doesn't do so is probably down to the a lack of need rather than anything else.

The fact that Linux appears to give absolute timestamp values accurate to 10s of microseconds is really an illusion. That they make it easy to perform elapsed time calculations is a bonus, but even then, even minor changes to the perl code that performs the elapsed time calculations, never mind the relatively speaking, incredibly tardy accesses to filesystems and IOwait states, mean that actually recording the values is probably going to take longer than the 1 milliseconds resolution that Win32 gives you to start with.

This reminds me of those opinion polls that conclude that a "majority of the people agree with xxxxx", on the basis of a 51.7% in favour and then add a ±3 margin of error in small print at the bottom of the screen/ article:)


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.

Replies are listed 'Best First'.
Re^2: Time::HiRes not that high on windows
by lepetitalbert (Abbot) on Oct 26, 2005 at 23:48 UTC

    Hi all

    while reading this, I tested it on my XP (ActivePerl 5.8) and got this :

    1130370142.0764
    1130370142.07657
    1130370142.07669
    1130370142.07679
    1130370142.07691
    1130370142.07701
    1130370142.07712
    1130370142.07723
    1130370142.07734
    1130370142.07745

    Has it maybe something to do with cygwin or have I missed something

    Have a nice day

      Wow! A rave from the grave :)

      This thread relates to an very old version of Time::HiRes. Later versions use a different system API to allow much higher resolution. For further reading see thread at Perl -de1 weirdness. and particularly Re^4: Perl -de1 weirdness..

      The resolution under windows is now comparable at around the 7 microsecond mark (on my machine. It will vary somewhat with the speed of your cpu). Certainly faster than a Perl script can report it.

      Though the weirdness with Time::HiRes when running under the debugger persists into 5.8.6:

      C:\perl5.8.6\bin>.\perl -MTime::HiRes=time -le"print time() for 1 .. 1 +0;" 1130373293.29716 1130373293.29732 1130373293.29739 1130373293.2976 1130373293.29766 1130373293.29784 1130373293.2979 1130373293.29807 1130373293.29814 1130373293.29831 C:\perl5.8.6\bin>.\perl -de1 Loading DB routines from perl5db.pl version 1.25 Editor support available. Enter h or `h h' for help, or `perldoc perldebug' for more help. main::(-e:1): 1 DB<1> use Time::HiRes 'time'; DB<2> print time(), $/ for 1 .. 10;; 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 1130373253.21875 DB<3> q

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://289891]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-18 01:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found