Alternative to time.sleep

5.4k views Asked by At

INTRO: It is well known that the accuracy of time.sleep is OS and computation load dependent. The accuracy in Windows is very poor.

Similarly to /questions/17499837 a method can implement a busy wait using the time.clock method as an alternative to time.sleep. Such an approach creates unnecessary load affecting other modules in the system. That is not desirable while doing simulations.

To reduce the amount of time spent in busy wait and not relying on the time.sleep, a class employs the method select.select and exploits the timeout attribute. See code below:

from sys import platform as _platform
import time, select, socket

class HighResolutionTimeStamp():
    __init = time.clock()
    __base = time.time()

    def __init__(self):
        self.__fd = socket.socket()
        self.dtts = time.clock if _platform == 'win32' else time.time

    def __del__(self):
        self.__fd.close()

    def get_high_resolution_dt(self):
        return HighResolutionTimeStamp.__base + self.dtts() if _platform == 'win32' else time.time()

    def busy_wait(self, wait_time):
        currentTime = self.dtts()
        while (self.dtts() <= currentTime + wait_time):
            pass

    def sleep(self, wait_time):
        currentTime = self.dtts()
        while (self.dtts() < (currentTime + wait_time - 0.001)):
            select.select([self.__fd], [], [], 0.001)
        while (self.dtts() < currentTime + wait_time):
            select.select([self.__fd], [], [], 0.0)

if __name__ == '__main__':
    st = 1.0/80.0
    it = 10
    ts = 1

    time.sleep(ts)
    hrdr = HighResolutionTimeStamp()
    total = hrdr.get_high_resolution_dt()
    for i in range(it):
        hrdr.busy_wait(st)
    print 'Ellapsed:', hrdr.get_high_resolution_dt() - total

    time.sleep(ts)
    total = hrdr.get_high_resolution_dt()
    for i in range(it):
        hrdr.sleep(st)
    print 'Ellapsed:', hrdr.get_high_resolution_dt() - total

    time.sleep(ts)
    total = hrdr.get_high_resolution_dt()
    for i in range(it):
        time.sleep(st)
    print 'Ellapsed:', hrdr.get_high_resolution_dt() - total

ENVIRONMENT: I'm using PortablePython2.7.6.1

PROBLEM: When the code is executed at the PyScripter or in the command line with PyScripter open in the background, the script above performs very accurate. Once the PyScripter is closed, the method sleep becomes inaccurate. I'm aware that the timeout for select.select should be inaccurate as time.sleep but in all cases, not as described above.

RESULTS:

Without PyScripter running in the background

C:\..\PortablePython2.7.6.1\App\python.exe highresolutiondt.py

Busy wait. Ellapsed: 0.125249385834

Sleep. Ellapsed: 0.15624165535

Time.sleep. Ellapsed: 0.156844139099

With PyScripter running in the background

C:\..\PortablePython2.7.6.1\App\python.exe highresolutiondt.py

Busy wait. Ellapsed: 0.125702142715

Sleep. Ellapsed: 0.125874519348

Time.sleep. Ellapsed: 0.120799064636
1

There are 1 answers

2
Lucas Urban On

This uses time since unix epoch, which, I'm pretty sure is more accurate, I don't use windows though, so I didn't test this out.

from time import time

def pause(secs):
    init_time = time()
    while time() < init_time+secs: pass

print("See ya in 10 seconds")
pause(10)
print("Heeeeeelooooo there")

Hope it helped