Laughing at myself
Bengt Richter
bokr at oz.net
Mon May 12 17:30:48 EDT 2003
On Mon, 12 May 2003 10:12:34 -0600, "Daniel Fackrell" <unlearned at DELETETHIS.learn2think.org> wrote:
>Just to make sure that everyone else can get some benefit from my
>self-induced pain:
>
>I have wasted a bit of time recently, wondering why Python doesn't offer a
>usleep() (sleep for microseconds) function. I had found the time module,
>and used its time.sleep(), but was frustrated that it didn't have a
>time.usleep() as well. After searching the web and the newsgroup archives,
>I finally figured I might get stuck implementing something like this at a
>low level.
>
>After all that, I was just reading a recent post reminding about the dangers
>of explicit type-checking reducing polymorphism, and somehow that reminded
>me of my problem. I had been assuming (courtesy of my strongly-typed
>background) that time.sleep() took in integer argument, but in fact it takes
>any numerical argument, so that:
>
>time.sleep(0.000001)
>
>works just fine, and apparently perfectly.
>
But note the limitations mentioned in the docs. YMMV according to platform
as to what happens in real time. Be aware that a "perfect" 1-microsecond sleep
is not too likely ;-)
A quick-n-dirty test follows (NT4, Python 2.2.2)
====< sleept.py >=================================================
from time import clock, sleep
import math
def sleept(n, delta):
snoozes = [0]*n
for i in xrange(n):
t = clock()
sleep(delta)
snoozes[i] = clock()-t
snoozes = map(float(-delta).__add__, snoozes) # errors from delta
mean = reduce(float.__add__, snoozes)/(n-1.0)
rms = reduce(float.__add__, map(lambda x:(x-mean)**2, snoozes))/(n-1.0)
return mean, math.sqrt(rms)
if __name__ == '__main__':
import sys
try:
n, delta = int(sys.argv[1]), float(sys.argv[2])
mean, sd = sleept(n, delta)
print 'Sleeping %s times for %f seconds => mean error %f, sd %f' % (
n, delta, mean, sd)
except Exception, e:
print e; print
print 'Usage: sleept nloops sleeptime'
==================================================================
Note what happens, presumably because the NT scheduler works on 10ms slices:
[13:38] C:\pywk\clp>sleept.py 1000 .002
Sleeping 1000 times for 0.002000 seconds => mean error 0.008042, sd 0.001010
[13:38] C:\pywk\clp>sleept.py 1000 .010
Sleeping 1000 times for 0.010000 seconds => mean error 0.000027, sd 0.000688
[13:38] C:\pywk\clp>sleept.py 1000 .012
Sleeping 1000 times for 0.012000 seconds => mean error 0.008111, sd 0.001428
The 2ms offset seems to cause a wait for the next tick, hence the ~ 8ms error.
The theory seems to hold with an 8 ms offset from an even tick:
[13:39] C:\pywk\clp>sleept.py 1000 .018
Sleeping 1000 times for 0.018000 seconds => mean error 0.002068, sd 0.001183
Or
[13:42] C:\pywk\clp>sleept.py 1000 .038
Sleeping 1000 times for 0.038000 seconds => mean error 0.002042, sd 0.000397
Of course, if other things are going on, YM will V even more, unless you
are running at real time priority and preempting whatever else. And apparently
signals can cut sleep short, so it can vary both ways. Most informative
would be a scatter plot showing requested vs actual sleep time. I think it
would be a fuzzy stair case with a sprinkling of outliers.
>Thanks to Alex Martelli for being the one who set me a bit closer to the
>true path.
I too am among the many who are indebted here, though I prefer to think we
all find our true paths ourselves. Of course, Alex leaves big footsteps ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list