Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Time::HiRes not that high on windows

by tos (Deacon)
on Sep 08, 2003 at 15:05 UTC ( #289785=perlquestion: print w/replies, xml ) Need Help??

tos has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

on my linux-system i get the desired highresoluted time-values which i want to use to generate reliable different filenames.

tos@tux ~/d/tsp/lab/dvlp/tos/too # uname -a && perl -v Linux tux 2.4.21-xfs #1 SMP Fre Jul 25 00:06:47 CEST 2003 i686 GNU/Lin +ux perl, v5.8.0 built for i386-linux-thread-multi # perl -we 'use Time::HiRes ("time");for ($i=1;$i<=10;$i++) {print tim +e,"\n"}' 1063031285.55356 1063031285.55394 1063031285.55404 1063031285.55414 1063031285.55423 1063031285.55432 1063031285.5545 1063031285.55462 1063031285.55472 1063031285.55481
Not so on the win2000/cygwin-system.
tos@SYS-10102 ~ # uname -a && perl -v CYGWIN_NT-5.1 SYS-10102 1.3.22(0.78/3/2) 2003-03-18 09:20 i686 unknown + unknown Cygwin This is perl, v5.8.0 built for cygwin-multi-64int # perl -we 'use Time::HiRes ("time");for ($i=1;$i<=10;$i++) {print tim +e,"\n"}' 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06805 1063032731.06905 1063032731.06905
It appears that here the resolution is only 1/1000 second.

Any explanations for this behavior

greetings, tos

Replies are listed 'Best First'.
Re: Time::HiRes not that high on windows
by jdtoronto (Prior) on Sep 08, 2003 at 15:38 UTC
    Resolution in the Windows system is limited. Generally speaking no better than 1ms no matter what you do. THis is due to the way Windows actually manages time in the PC hardware.

    *nix variants on PC hardware handle it very differently.

    There were a number of discussions a year or so back centered around some physiological event timing using the DJGPP compiler. This may explain the problem further but sadly I don't think it will offer a solution.

    There is some discussion here about higher resolution - to 100ns - I have never tried the technique or investigated it further. jdtoronto

      Windows uses 'ticks' of between 10ms and 100ms (varies among versions). If you want higher resolution timing, then you can use the high-resolution timer [via QueryPerformanceFrequency() and QueryPerformanceCounter()] or a multimedia timer. I've not seen interfaces to either of these from Perl, however.

                      - tye
Re: Time::HiRes not that high on windows
by BrowserUk (Pope) on Sep 08, 2003 at 22:12 UTC

    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.

      Hi all

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


      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 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.
Re: Time::HiRes not that high on windows
by Abigail-II (Bishop) on Sep 08, 2003 at 15:14 UTC
    Ask Microsoft. All Time::HiRes is doing is providing an interface with the system libraries. If the system doesn't provide time with a resolution more than 1/1000th of a second, neither can Time::HiRes. If the system uses a different interface than Time::HiRes is using, Time::HiRes won't know.

    See the manual page of Time::HiRes, which system functions Time::HiRes is trying to use, and see your system manuals to see which one they provide.


Re: Time::HiRes not that high on windows
by perrin (Chancellor) on Sep 08, 2003 at 17:42 UTC
    I'm not sure this will work any better, but take a look at the approach using select() documented in perlfunc or here. It may be using the exact same approach as Time::HiRes though.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://289785]
Approved by sgifford
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2021-01-23 05:05 GMT
Find Nodes?
    Voting Booth?