Time::HiRes usleep on windows strange behaviour...please please help!!

M

mastermagrath

Hi,

I had asked a question recently and received a pointer to the problem
(thanks Xho). So i've basically found what the culprit is but now i
don't know what i can do to get around it.
Basically i run activestate perl v.5.8 on windows.
The heart of my script relies on the user being able to alter the sleep
time in a loop by at least milliseconds but preferably by microseconds.
What i have discovered is strange.
If i use usleep (for microsecond granularity) or win32::sleep (for
millisecond granualarity) they both produce weird actual sleep times
based on what value is supplied to them. Here is an example with
usleep:

Any value between 1 - 999 microseconds actually only sleep for 10
microseconds.
Any value between 1000 - 10990 microseconds actually sleeps for 10000
microseconds.
Any value between 11000 - 20990 microseconds actually sleeps for 20000
microseconds.

This trend continues, what i dont understand is it cant be the
granularity of usleep because it can sleep for 10 microseconds so does
anyone have any idea why usleep doesn't seem interested in sleeping for
certain values here?
If i use win32::sleep with milliseconds a similar thing happens. I'd
sell a kidney to know this as its driving me crazy!!!
The worst thing is i've spent weeks writing a fairly large script and
i'm panicking now as it is useless without the abilty to control the
loop execution rate.
 
T

Thomas Kratz

mastermagrath said:
Hi,

I had asked a question recently and received a pointer to the problem
(thanks Xho). So i've basically found what the culprit is but now i
don't know what i can do to get around it.
Basically i run activestate perl v.5.8 on windows.
The heart of my script relies on the user being able to alter the sleep
time in a loop by at least milliseconds but preferably by microseconds.
What i have discovered is strange.
If i use usleep (for microsecond granularity) or win32::sleep (for
millisecond granualarity) they both produce weird actual sleep times
based on what value is supplied to them. Here is an example with
usleep:

Any value between 1 - 999 microseconds actually only sleep for 10
microseconds.
Any value between 1000 - 10990 microseconds actually sleeps for 10000
microseconds.
Any value between 11000 - 20990 microseconds actually sleeps for 20000
microseconds.

I have done what you should have; namly put together a simple script
testing the above, that anyone can run (please see the posting guidelines
for further posts)

use strict;
use warnings;

use Time::HiRes qw(time usleep);

my $t0 = time;
my $i = 0;

do {
usleep($ARGV[0]);
printf "%.6f\n", time - $t0;
} until ++$i == 10;

The results on my XP machine are shown at the bottom of this post. The
granularity seems to be about 1 millisecond. I cannot confirm your results.

For a short explanation what granularity really means (it is *not* the
dimension of the parameter you pass to the function) have a look at:

http://www.greyware.com/software/domaintime/technical/accuracy/interpolation.asp

and/or google for the term.

Thomas

D:\tmp\perl>perl hiresttest.pl 100
0.000062
0.000515
0.000793
0.000961
0.001113
0.001256
0.001408
0.001553
0.001698
0.001870

D:\tmp\perl>perl hiresttest.pl 500
0.000031
0.000490
0.000662
0.000817
0.000968
0.001118
0.001262
0.001411
0.001573
0.001720

D:\tmp\perl>perl hiresttest.pl 1000
0.000441
0.001439
0.002442
0.003446
0.004448
0.005450
0.006477
0.007459
0.008460
0.009470

D:\tmp\perl>perl hiresttest.pl 2000
0.001980
0.003981
0.005988
0.007998
0.009999
0.012005
0.014011
0.016022
0.018028
0.020030

D:\tmp\perl>perl hiresttest.pl 5000
0.004722
0.026823
0.031837
0.036961
0.041836
0.046854
0.051866
0.056874
0.061889
0.066910

D:\tmp\perl>perl hiresttest.pl 10000
0.009952
0.033031
0.043055
0.053157
0.063109
0.073169
0.083206
0.093240
0.103230
0.113281

D:\tmp\perl>perl hiresttest.pl 15000
0.015043
0.030083
0.045118
0.060168
0.075219
0.090267
0.105311
0.120361
0.135423
0.150455

D:\tmp\perl>perl hiresttest.pl 20000
0.019711
0.039760
0.059822
0.079887
0.099973
0.120013
0.140078
0.160143
0.180229
0.200273

Thomas

--
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
mastermagrath
Any value between 1 - 999 microseconds actually only sleep for 10
microseconds.

10 microseconds is about a typical overhead of a system call. So I
would not say it sleeps at all - just returns immediately.
Any value between 1000 - 10990 microseconds actually sleeps for 10000
microseconds.
Any value between 11000 - 20990 microseconds actually sleeps for 20000
microseconds.

So the rounding is to a multiple of 1/100sec ticks. This is the
expected timeslice resolution on most systems. The choice between
rounding up/down is a little bit weird, but not absurd.

So I would put it in "as expected" category...

Hope this helps,
Ilya
 
M

mastermagrath

Thanks all for your replies, what confuses me is what is the point in
having high res functions when you say that a rounding of 1/100sec
ticks is expected?!!
How then do programmers generally control loops to finer timeslices,
i'm sure it must be quite common to accurately control the frequency of
iteration of loops to a finer frequency than 1/100??

I guess now my question is how can i possibly do what i need to do. The
loop i refer to controls the number of packets/sec offered to a UDP
socket.
 
R

robic0

Your timer resolution will be equal to the time duration between system ticks.
This is a value directly dependent on system load; higher load, less accuracy.
Wrong, miscosecond is an absolute on NT, no matter what the load.
Near real time (POSIX). Real time needs finer graduation.
Interrupts are in the kernel, driven by cpu cycles. Microseconds may
not be enough (or may be +/- %5.
RTOS is the control of choice. But, no Perl program needs or can get
microsecond granularity.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top