3

Python 3.11 introduces a high-resolution timer for time.sleep on Windows. Previously, the best sleep resolution was 1ms (although in practice it was often 16ms unless you engaged in winmm timeBeginPeriod trickery).

Upon upgrading to Python 3.11, I expected time.sleep to become vastly more accurate, since the documentation specifies that the new high-resolution timer on Windows "provides resolution of 100 nanoseconds".

However, if I pass a very small value to time.sleep, the best I seem to get is ~0.5 milliseconds. Not bad, but a far cry from "100 nanoseconds". I am running with Python 3.11.4 on Windows 11 Pro 22H2.

For instance, consider the following snippet:

import time
start = time.time_ns()
time.sleep(1e-6)  # sleep for 1 microsecond
end = time.time_ns()
print((end - start) / 1e3)  # prints anywhere between 200-800 microseconds, not ~1 microsecond

I can also plot this resolution of 0.5ms across a larger range of inputs:

import time
from matplotlib import pyplot as plt

expected = []
actual = []
for t in range(1, 10_000, 10):
    start = time.perf_counter_ns()
    time.sleep(t * 1e-6)  # sleep for `t` microseconds
    end = time.perf_counter_ns()
    expected.append(t)
    actual.append((end - start) / 1e3)
plt.plot([1, 10_000], [1, 10_000], label="Expected", c="orange")
plt.scatter(expected, actual, label="Actual")
plt.xlabel("Input to time.sleep (microseconds)")
plt.ylabel("Result (microseconds)")
plt.legend()
plt.show()

Which produces this plot. You can see the "steps" every 500 microseconds.

How would I actually get something close to 100ns sleep resolution?

0 Answers0