Is there a more precise alternative to time.sleep() in Python?
Question:
So I was looking for a more precise alternative to time.sleep()
in Python but couldn’t find any good options. Does anyone know if there is a more accurate alternative with at least millisecond precision?
Something like this:
precise_delay(3.141)
# Pauses the program for exactly 3.141 seconds
And no, I tried, and time.sleep()
is not very precise.
I did some testing using time.perf_counter()
and the results varied from 0.005
to 0.015
even tho I entered 0.001
.
Here are the precise times:
0.013264300000628282
, 0.005171099999643047
and 0.015634399999726156
Answers:
Nvm I found a way to do it:
import time
def precise_delay(delay_amount):
prv_t = time.perf_counter()
while round((time.perf_counter() - prv_t) * 1000) / 1000 - 0.001 <= delay_amount:
pass
time.sleep
switches to another thread while it sleeps. That other thread will typically run for its entire time slice (10-15ms, but depends on the OS).
What you want is a spin wait that doesn’t give up the thread, but uses more CPU. time.perf_counter_ns
has the best precision counter:
from time import perf_counter_ns
def spinwait_us(delay):
target = perf_counter_ns() + delay * 1000
while perf_counter_ns() < target:
pass
Timings:
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(1)"
200000 loops, best of 5: 1.3 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(10)"
20000 loops, best of 5: 10.3 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(100)"
2000 loops, best of 5: 100 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(1000)"
200 loops, best of 5: 1 msec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(905)"
500 loops, best of 5: 905 usec per loop
Seems to run over about about 300ns on my system. So pretty accurate.
So I was looking for a more precise alternative to time.sleep()
in Python but couldn’t find any good options. Does anyone know if there is a more accurate alternative with at least millisecond precision?
Something like this:
precise_delay(3.141)
# Pauses the program for exactly 3.141 seconds
And no, I tried, and time.sleep()
is not very precise.
I did some testing using time.perf_counter()
and the results varied from 0.005
to 0.015
even tho I entered 0.001
.
Here are the precise times:
0.013264300000628282
, 0.005171099999643047
and 0.015634399999726156
Nvm I found a way to do it:
import time
def precise_delay(delay_amount):
prv_t = time.perf_counter()
while round((time.perf_counter() - prv_t) * 1000) / 1000 - 0.001 <= delay_amount:
pass
time.sleep
switches to another thread while it sleeps. That other thread will typically run for its entire time slice (10-15ms, but depends on the OS).
What you want is a spin wait that doesn’t give up the thread, but uses more CPU. time.perf_counter_ns
has the best precision counter:
from time import perf_counter_ns
def spinwait_us(delay):
target = perf_counter_ns() + delay * 1000
while perf_counter_ns() < target:
pass
Timings:
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(1)"
200000 loops, best of 5: 1.3 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(10)"
20000 loops, best of 5: 10.3 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(100)"
2000 loops, best of 5: 100 usec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(1000)"
200 loops, best of 5: 1 msec per loop
C:>py -m timeit -s "from test import spinwait_us" "spinwait_us(905)"
500 loops, best of 5: 905 usec per loop
Seems to run over about about 300ns on my system. So pretty accurate.