I have a need for a time.clock() with >0.000016 second (16us) accuracy.
The sleep() (on Python 2.3, Win32, at least) has a .001s limit. Is it lower/better on other's platforms?

I tried this test code, 2.4GHz P4
Python 2.3.3 (#51, Dec 18 2003, 20:22:39) [MSC v.1200 32 bit (Intel)] on win32

import time
t0 = time.clock()
t1 = time.clock()
t2 = time.clock()
t3 = time.clock()
t4 = time.clock()
t5 = time.clock()
print (-t0+t5)/5.
print t1-t0
print t2-t1
print t3-t2
print t4-t3
print t5-t4

>>>
ave 0.000342754564927
0.000321028401686
0.00030348379596
0.000297101358228
0.000295895991258

I had also considered forking a thread that would spin a loop checking time.clock() and firing the TTL pulse after the appropriate interval, but the real, ultimate resolution of time.clock() appears to be ~.00035s. If I increase process priority to real-time, it is ~.00028s and more stable.


I also tried some other code - times.py (attached)
suggested by:
http://66.102.7.104/search?q=cache:bLJ1F3Xxl-sJ:edily.progiciels-bpi.ca/showfile.html%3Fname%3Dcourriel/c%C3%A9duleur%26index%3D1+accuracy+time+sleep+python&hl=en&client=firefox-a
Note lines 15, 16, 17 - I still don't get why it (kind of) works.
15 and 17 have no different results when you ask for a delay<.001 (.001 is the slowest sleep() possible). But, it would seem that this should be forcing the minimum delay over 1000us!
For mydelay(.00016) the results are stable, but for mydelay(.000016) the actual average delay trends down. (!)


I then tried compiling an exe that uses select(), but it fails to delay:
#include <winsock2.h>
int main()
        {
    struct timeval time;
    time.tv_sec = 10;
    time.tv_usec = 100000;

    select (0, NULL, NULL, NULL, &time);
    return 0;
    }


I then tried Python socket() - ~consistent, but the time control is not possible: In select(iwtd, owtd, ewtd[, timeout])  the timeout gotten "jumps" relative to the asked-for time when using small times (<.001), ie, .000001=>976us, .0000009=>79us.


I also tried a shot at compiling a command exe to do delays with RDTSC from:
http://216.239.63.104/search?q=cache:_HdQc03oTAIJ:www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20556300.html+accuracy+time+sleep+python&hl=en&client=firefox-a
using RDTSC - Read Time Stamp Counter info:
http://www.midnightbeach.com/jon/pubs/rdtsc.htm
I called it dosDelay (attached), but it does not seem to do any delaying...

I would make it a Windows or Python DLL if it did, RDTSC would be a great timing boon to those using 586 CPUs. On Windows there is still the multi-task issue, but setting the process to real-time helps a lot. R-T Linux users would benefit also.

Ray
http://rjs.org

import time

mytime = time.time ## optimization
sleep = time.sleep
clock = time.clock

def mydelay(delay):
    global logical_time
    physical_time = mytime()
    try:
        logical_time = logical_time + delay
    except NameError:
        logical_time = physical_time + delay
    if logical_time > physical_time:
        sleep(logical_time - physical_time)
        #sleep(.0001) ## same as sleep(0)!
        #sleep(.001)


p = 0.
d1 = 0.
d2 = 0.
looped = 0.
howMany = 100
for i in range(20):
    ## timer for pass in a for loop
    t1 = clock()
    for j in range(howMany):
        pass
    p += (clock()-t1)

    t1 = clock()
    for j in range(howMany):
        mydelay(.0000001)     ## ~minumum useable
    d1 += (clock()-t1)

    t1 = clock()
    for j in range(howMany):
        mydelay(.00016)      ## one turbine degree
    d2 += (clock()-t1)

    looped+= howMany
    print 'micro sec: %.1f %.1f %.1f' % (1000000*p/looped, 1000000*d1/looped, 
1000000*(d2)/looped)
import time
import select
import socket

HOST = ''                 # Symbolic name meaning the local host
PORT = 50007              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

mytime = time.time ## optimization
sleep = time.sleep
clock = time.clock


p = 0.
d1 = 0.
d2 = 0.
looped = 0.
howMany = 100
for i in range(20):
    ## timer for pass in a for loop
    t1 = clock()
    for j in range(howMany):
        pass
    p += (clock()-t1)

    t1 = clock()
    for j in range(howMany):
        select.select([s], [], [], .0000009)
        #select.select([s], [], [], .000001) ## causes a timing jump!
    d1 += (clock()-t1)

    t1 = clock()
    for j in range(howMany):
        select.select([s], [], [], .0004)
    d2 += (clock()-t1)

    looped+= howMany
    print 'micro sec: %.1f %.1f %.1f' % (1000000*p/looped, 1000000*d1/looped, 
1000000*(d2)/looped)
// dosDelay.cpp : Defines the entry point for the console application.


struct sysclock_t {
   int LL, LH, HL, HH;
};

struct tv time;
time.tv_sec = num_seconds_to_sleep;
time.tv_usec = num_microseconds_to_sleep;

select(NULL,NULL,NULL,& time);

void main()
{
   int ns= 1000000;
   // make the sleep in 100th nanoseconds.
   ns = (ns + 99)/100;
   //ns -= FACTOR;

   __asm {
      rdtsc
      // clock in EDX:EAX
      // we ignore EDX since we asume ns is
      // of shorter duration than that.
      add eax,dword ptr ns
      mov ebx,eax // save eax into ebx.
      jnc loop2

      // new time is after wrapping around
loop1:
      rdtsc
      // again we ignore EDX
      // wait for time to wrap around.
      cmp eax,ebx
      jae loop1

// Time has wrapped around and present time < wait time.
loop2:
      rdtsc
      // again we ignore EDX
      cmp eax,ebx
      jb loop2
    }
}
_______________________________________________
Python-win32 mailing list
Python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32

Reply via email to