Lisp HUG Maillist Archive

Time to sleep under different platforms

I tested the accuracy of the sleep function under different conditions (see the table below). 

The table was generated using a very simple function, taking the elapsed time for comparing performance.
I could have done some sampling but these one run results are quite consistent over many repetitions. 

The function I used is the following, called form the listener on a freshly launched LW: 

(dolist (sec '(1 0.5 0.1 0.05 0.01 0.005 0.001)) (time (sleep sec)))

It is a known fact that Windows XP cannot give accurate time measurement under about 15 msec. This problem is apparently solved in Vista.

Notice that I also ran a test with a Vista virtual image on a MacPro with excellent accuracy (within 1msec). 

Does anyone know of a Lisp solution to give Windows XP a better time resolution?

Thanks for your replies. 

Bruno

Machine  OS  LW (Sleep x)
    
      1.000  0.500  0.100  0.050  0.010  0.005  0.001
MacPro
MacOS X 10.4.6  6.0 64bit  1.001  0.500  0.100  0.050  0.010  0.005  0.002
                       Vista Business 
6.0 32bit  1.001  0.501  0.101  0.051  0.010  0.006  0.002
DELL - Latitude|E6500 
XP 32  5.1 32bit  1.016  0.516  0.109  0.063  0.015  0.016  0.016
DELL - Precision|M6400 
XP 64  6.0 32bit  1.000  0.500  0.110  0.062  0.016  0.015  0.016

Re: Time to sleep under different platforms

It's strange that sleep is much more accurate than the functions of the mp
package 
With an intel mac :

Compute the number of ticks in one second :

(loop with end = (+ 1000 (get-internal-real-time))
      for time = (get-internal-real-time)
      while (< time end)
      do (sleep 0.001)
      count time)

=> 500 (which confirm perfectly your observation : on mac the better
resolution - with sleep - is 2ms) and sleep gives a nive regularity as show
this other test :

Compute the min, max and average interval between ticks :

(loop with prev
      with end = (+ 1000 (get-internal-real-time))
      for time = (get-internal-real-time)
      for interval = (and prev (- time prev))
      for i from 0
      while (< time end)
      do (sleep 0.001)
      when interval collect interval
      and maximize interval into max
      and minimize interval into min
      and sum interval into mean
      do (setf prev time)
      finally (return (list min max (float (/ mean i))))) => (2 3 2.0040162)

The same with (mp:process-wait-with-timeout "" 0.001) in place of sleep :

Number of ticks => around 110
Min and max interval => (1 12 8.910714)

MP seems to be limited to a 10 ms precision (but less regular than sleep)

In the other side, using some low level procedure of the mac, I can obtain a
1 ms resolution and even better. So the OS is not all. Many programs which
need a high level of time precision  run very well on XP. Don't you think
that you can obtain a better resolution by using some specific OS
functionalities ? 

Best regards

Denis


Le 21/07/10 19:50, « [NOM] » <[ADRESSE]> a écrit :

> I tested the accuracy of the sleep function under different conditions (see
> the table below).
> 
> The table was generated using a very simple function, taking the elapsed time
> for comparing performance.
> I could have done some sampling but these one run results are quite consistent
> over many repetitions.
> 
> The function I used is the following, called form the listener on a freshly
> launched LW: 
> 
> (dolist (sec '(1 0.5 0.1 0.05 0.01 0.005 0.001)) (time (sleep sec)))
> 
> It is a known fact that Windows XP cannot give accurate time measurement under
> about 15 msec. This problem is apparently solved in Vista.
> 
> Notice that I also ran a test with a Vista virtual image on a MacPro with
> excellent accuracy (within 1msec).
> 
> Does anyone know of a Lisp solution to give Windows XP a better time
> resolution?
> 
> Thanks for your replies.
> 
> Bruno
> 
> Machine                      OS             LW
> (Sleep x)
>                                                       1.000   0.500   0.100
> 0.050   0.010   0.005   0.001
> MacPro                MacOS X 10.4.6     6.0 64bit   1.001   0.500   0.100
> 0.050   0.010   0.005   0.002
>                        Vista Business     6.0 32bit   1.001   0.501   0.101
> 0.051   0.010   0.006   0.002
> DELL - Latitude|E6500      XP 32          5.1 32bit   1.016   0.516   0.109
> 0.063   0.015   0.016   0.016
> DELL - Precision|M6400     XP 64          6.0 32bit   1.000   0.500   0.110
> 0.062   0.016   0.015   0.016
> 


-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Time to sleep under different platforms

On Wed, 21 Jul 2010 20:46:43 +0100, Denis Pousseur  
<denis.pousseur@gmail.com> wrote:


> (loop with end = (+ 1000 (get-internal-real-time))
>       for time = (get-internal-real-time)
>       while (< time end)
>       do (sleep 0.001)
>       count time)

This yielded 998 in W7 64.

> (loop with prev
>       with end = (+ 1000 (get-internal-real-time))
>       for time = (get-internal-real-time)
>       for interval = (and prev (- time prev))
>       for i from 0
>       while (< time end)
>       do (sleep 0.001)
>       when interval collect interval
>       and maximize interval into max
>       and minimize interval into min
>       and sum interval into mean
>       do (setf prev time)
>       finally (return (list min max (float (/ mean i)))))

That evaluated to (1 3 1.0070565).

> The same with (mp:process-wait-with-timeout "" 0.001) in place of sleep :

(1 3 1.0060423) with the max going into 5 at most.

BTW, interesting style of LOOPing.


Re: Time to sleep under different platforms

Thanks Denis, 

very interesting loops! 
That alone was worth my posting. 

> (loop with end = (+ 1000 (get-internal-real-time))
>      for time = (get-internal-real-time)
>      while (< time end)
>      do (sleep 0.001)
>      count time)
> => 500 (which confirm perfectly your observation : on mac the better
> resolution - with sleep - is 2ms) and sleep gives a nive regularity as show
> this other test :

Gives me 964. As I said in my original message I only ran the function once. I was not making a claim that the precision on my MacPro (2 X 3 GHz Quad-Core Intel Xeon) was 2 msec. 
Yuri seems to have the fastest machine on W7 64 with 998. 
In my virtual Vista image the result is 512.

> (loop with prev
>      with end = (+ 1000 (get-internal-real-time))
>      for time = (get-internal-real-time)
>      for interval = (and prev (- time prev))
>      for i from 0
>      while (< time end)
>      do (sleep 0.001)
>      when interval collect interval
>      and maximize interval into max
>      and minimize interval into min
>      and sum interval into mean
>      do (setf prev time)
>      finally (return (list min max (float (/ mean i))))) => (2 3 2.0040162)

Result is (1 2 1.0560254) .
Less variability (did not get 3) than Yuri's machine but not as precise (1 3 1.0070565).
In my virtual Vista image the result is (1 3 1.9607073)

> The same with (mp:process-wait-with-timeout "" 0.001) in place of sleep :

Result is (0 2 1.0449791)
Same observations as before. The questionable value is the zero minimum. This would confirm the lack of precision of mp:process-wait-with-timeout because in at least in one instance, it did not wait for 1 msec.  
In my virtual Vista image the result is (1 9 1.9762377). Ouch, 9 as a maximum.

> 
> In the other side, using some low level procedure of the mac, I can obtain a
> 1 ms resolution and even better. So the OS is not all. Many programs which
> need a high level of time precision  run very well on XP. Don't you think
> that you can obtain a better resolution by using some specific OS
> functionalities ? 

Yes using some OS specific functionality (MacOS or Windows) is certainly the way to proceed to obtain the maximum precision. 


> 
> Le 21/07/10 19:50, « [NOM] » <[ADRESSE]> a écrit :
> 
>> I tested the accuracy of the sleep function under different conditions (see
>> the table below).
>> 
>> The table was generated using a very simple function, taking the elapsed time
>> for comparing performance.
>> I could have done some sampling but these one run results are quite consistent
>> over many repetitions.
>> 
>> The function I used is the following, called form the listener on a freshly
>> launched LW: 
>> 
>> (dolist (sec '(1 0.5 0.1 0.05 0.01 0.005 0.001)) (time (sleep sec)))
>> 
>> It is a known fact that Windows XP cannot give accurate time measurement under
>> about 15 msec. This problem is apparently solved in Vista.
>> 
>> Notice that I also ran a test with a Vista virtual image on a MacPro with
>> excellent accuracy (within 1msec).
>> 
>> Does anyone know of a Lisp solution to give Windows XP a better time
>> resolution?
>> 
>> Thanks for your replies.
>> 
>> Bruno
>> 
>> Machine                      OS             LW
>> (Sleep x)
>>                                                      1.000   0.500   0.100
>> 0.050   0.010   0.005   0.001
>> MacPro                MacOS X 10.4.6     6.0 64bit   1.001   0.500   0.100
>> 0.050   0.010   0.005   0.002
>>                       Vista Business     6.0 32bit   1.001   0.501   0.101
>> 0.051   0.010   0.006   0.002
>> DELL - Latitude|E6500      XP 32          5.1 32bit   1.016   0.516   0.109
>> 0.063   0.015   0.016   0.016
>> DELL - Precision|M6400     XP 64          6.0 32bit   1.000   0.500   0.110
>> 0.062   0.016   0.015   0.016
>> 
> 
> 
> -------------------------------------------------------
> Denis Pousseur
> 70 rue de Wansijn
> 1180 Bruxelles, Belgique
> 
> Tel : 32 (0)2 219 31 09
> Mail :  denis.pousseur@gmail.com
> -------------------------------------------------------
> 
> 


Re: Time to sleep under different platforms

On Jul 21, 2010, at 3:46 PM, Denis Pousseur wrote:

> Compute the number of ticks in one second :

Isn't this what cl::internal-time-units-per-second is for?

warmest regards,

Ralph


Raffael Cavallaro
raffaelcavallaro@me.com






Re: Time to sleep under different platforms

On my system cl::internal-time-units-per-second return 1000 (and I suppose
on every systems running lw). The result of the test is 500, so it's not the
same thing. But you're right, it's certainly much precise to say : this test
compute the EFFECTIVE number of ticks per second.

Best regards

Denis

Le 22/07/10 1:56, « [NOM] » <[ADRESSE]> a écrit :

> 
> 
> On Jul 21, 2010, at 3:46 PM, Denis Pousseur wrote:
> 
>> Compute the number of ticks in one second :
> 
> Isn't this what cl::internal-time-units-per-second is for?
> 
> warmest regards,
> 
> Ralph
> 
> 
> Raffael Cavallaro
> raffaelcavallaro@me.com
> 
> 
> 
> 
> 

-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Time to sleep under different platforms

On Jul 22, 2010, at 7:53 AM, Denis Pousseur wrote:

> On my system cl::internal-time-units-per-second return 1000 (and I suppose
> on every systems running lw). The result of the test is 500, so it's not the
> same thing. But you're right, it's certainly much precise to say : this test
> compute the EFFECTIVE number of ticks per second.


What you're measuring here is the overhead of doing all of these things every time though the loop
1. the loop counter increment
2. get-internal-real-time
3. the comparison with the start time
4. the call to sleep

these things do take some finite time to execute. The counter increment and some sort of comparison are unavoidable - we can't have a finite loop without them, and the calls to sleep are precisely what we want to time. However, if you want to see how far off internal-time-units-per second is wrt sleep, you shouldn't also be doing a call to get-internal-real-time every pass though the loop, and to be precise, we should back out the time for an empty loop of the same size. As it turns out, the empty loop time is negligible (< 1 millisecond), so we can ignore it.

so:

(defun dotimes-ticktest (&optional (times 1000))
  (declare (optimize (speed 3) (safety 0) (debug 0) (compilation-speed 0)
                     (space 0) (fixnum-safety 0) (float 0)))
  (let* ((sleeptime (float (/ internal-time-units-per-second) 0.0s0))
         (start (get-internal-real-time))
         (stop
          (mp:with-interrupts-blocked
            (dotimes (n times (get-internal-real-time))
              (declare (fixnum n))
              (sleep sleeptime)))))
    (declare (fixnum start stop) (single-float sleeptime))
    (float (/ (- stop start) times))))

on my machine this returns 1.11, or an 11% overhead for the calls to sleep. I get similar results with Clozure Common Lisp and sbcl btw - both show about 10-11% overhead for a large number of calls to sleep.

warmest regards,

Ralph




Raffael Cavallaro
raffaelcavallaro@me.com






Re: Time to sleep under different platforms

You're perfectly right. My goal was not to develop a tool to measure the
sleep performances. Just to speak about the difference between sleep and the
mp package functions. I suppose that the difference observed with this loop
are not contradicted by your test (at least if we speak of practical
situations and not of pure theory).

Naturally a scheduler cannot be based on a loop like this one, as you said
the time for operations must be included. Moreover, it is why it's not
possible to have a ms scheduler on pure lisp, even with sleep, because to
have one wee need a smaller time definition than ms. The procedure I use on
mac is based on machine time at a resolution of 1.000.000 per second on an
intel mac (less on power pc). With this resolution it's possible to include
the time of the tasks in the computation and have, globally, an ms
resolution (the wait function is not based on an interval but on a point to
reach always relative to the start point).

This message was also to said that something similar is certainly possible
on XP, otherwise I really don't know how some software I used on XP
(especially for sound edition) could works at a 88khz definition...

Anyway, thanks for your very interesting demonstration !

Best regards

Denis



Le 22/07/10 16:43, « [NOM] » <[ADRESSE]> a écrit :

> 
> 
> On Jul 22, 2010, at 7:53 AM, Denis Pousseur wrote:
> 
>> On my system cl::internal-time-units-per-second return 1000 (and I suppose
>> on every systems running lw). The result of the test is 500, so it's not the
>> same thing. But you're right, it's certainly much precise to say : this test
>> compute the EFFECTIVE number of ticks per second.
> 
> 
> What you're measuring here is the overhead of doing all of these things every
> time though the loop
> 1. the loop counter increment
> 2. get-internal-real-time
> 3. the comparison with the start time
> 4. the call to sleep
> 
> these things do take some finite time to execute. The counter increment and
> some sort of comparison are unavoidable - we can't have a finite loop without
> them, and the calls to sleep are precisely what we want to time. However, if
> you want to see how far off internal-time-units-per second is wrt sleep, you
> shouldn't also be doing a call to get-internal-real-time every pass though the
> loop, and to be precise, we should back out the time for an empty loop of the
> same size. As it turns out, the empty loop time is negligible (< 1
> millisecond), so we can ignore it.
> 
> so:
> 
> (defun dotimes-ticktest (&optional (times 1000))
>   (declare (optimize (speed 3) (safety 0) (debug 0) (compilation-speed 0)
>                      (space 0) (fixnum-safety 0) (float 0)))
>   (let* ((sleeptime (float (/ internal-time-units-per-second) 0.0s0))
>          (start (get-internal-real-time))
>          (stop
>           (mp:with-interrupts-blocked
>             (dotimes (n times (get-internal-real-time))
>               (declare (fixnum n))
>               (sleep sleeptime)))))
>     (declare (fixnum start stop) (single-float sleeptime))
>     (float (/ (- stop start) times))))
> 
> on my machine this returns 1.11, or an 11% overhead for the calls to sleep. I
> get similar results with Clozure Common Lisp and sbcl btw - both show about
> 10-11% overhead for a large number of calls to sleep.
> 
> warmest regards,
> 
> Ralph
> 
> 
> 
> 
> Raffael Cavallaro
> raffaelcavallaro@me.com
> 
> 
> 
> 
> 

-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique

Tel : 32 (0)2 219 31 09
Mail :  denis.pousseur@gmail.com
-------------------------------------------------------



Re: Time to sleep under different platforms

On Thu, 22 Jul 2010 17:48:05 +0100, Denis Pousseur  
<denis.pousseur@gmail.com> wrote:

> otherwise I really don't know how some software I used on XP
> (especially for sound edition) could works at a 88khz definition...

Well, for sound processing 50 frames per second is fairly acceptable, that  
amounts to 20 ms buffers, which is manageable even with interpreted code,  
as the examples have shown.


Re: Time to sleep under different platforms

> It is a known fact that Windows XP cannot give accurate time measurement
> under about 15 msec. This problem is apparently solved in Vista.

How To Use QueryPerformanceCounter to Time Code

http://support.microsoft.com/kb/172338


Updated at: 2020-12-10 08:39 UTC