classification
Title: [Windows] time.sleep() should use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
Type: enhancement Stage: patch review
Components: Library (Lib), Windows Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Livius, corona10, eryksun, paul.moore, steve.dower, tim.golden, vstinner, zach.ware
Priority: normal Keywords: patch

Created on 2021-10-11 08:28 by vstinner, last changed 2021-10-24 16:03 by corona10.

Files
File name Uploaded Description Edit
bpo-45429.py corona10, 2021-10-24 16:03
Pull Requests
URL Status Linked Edit
PR 29203 open corona10, 2021-10-24 16:01
Messages (7)
msg403631 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-10-11 08:28
In bpo-21302, the Windows implementation of time.sleep() was modified to use a waitable timer:

New changeset 58f8adfda3c2b42f654a55500e8e3a6433cb95f2 by Victor Stinner in branch 'main':
bpo-21302: time.sleep() uses waitable timer on Windows (GH-28483)
https://github.com/python/cpython/commit/58f8adfda3c2b42f654a55500e8e3a6433cb95f2

It now calls the functions:

* CreateWaitableTimerW()
* SetWaitableTimer()
* WaitForMultipleObjects()

While SetWaitableTimer() has a resolution of 100 ns, the timer has a resolution of 15.6 ms in practice.

We could use the undocumented CREATE_WAITABLE_TIMER_HIGH_RESOLUTION flag with CreateWaitableTimerEx(). See: https://bugs.python.org/issue21302#msg403550

See also:

* https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
* https://vstinner.readthedocs.io/windows.html#time
msg403634 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-10-11 08:32
See also: https://groups.google.com/a/chromium.org/g/scheduler-dev/c/0GlSPYreJeY
msg403635 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-10-11 08:38
The Go programming language called timeBeginPeriod(1) to get more accurate timers. With the following change, it can now use a high resolution timer (CREATE_WAITABLE_TIMER_HIGH_RESOLUTION) to sleep:
https://go-review.googlesource.com/c/go/+/248699/
msg403659 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-10-11 15:59
See also bpo-19007: "precise time.time() under Windows 8: use GetSystemTimePreciseAsFileTime".
msg403703 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021-10-11 23:26
It's up to the core devs whether or not Python should try to use a high-resolution timer, which is currently undocumented in the Windows API and implemented only in recent releases of Windows 10 and 11. But if this does get supported, the code should fall back on creating a normal timer if CREATE_WAITABLE_TIMER_HIGH_RESOLUTION makes the call fail. For example:

    #ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
    #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
    #endif

        LARGE_INTEGER relative_timeout;
        // No need to check for integer overflow, both types are signed
        assert(sizeof(relative_timeout) == sizeof(timeout_100ns));
        // SetWaitableTimerEx(): a negative due time is relative
        relative_timeout.QuadPart = -timeout_100ns;
        DWORD flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION;

    create_timer:

        HANDLE timer = CreateWaitableTimerExW(NULL, NULL, flags, TIMER_ALL_ACCESS);
        if (timer == NULL)
        {
            if (flags && GetLastError() == ERROR_INVALID_PARAMETER) {
                // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is not supported.
                flags = 0;
                goto create_timer;
            }
            PyErr_SetFromWindowsErr(0);
            return -1;
        }

        if (!SetWaitableTimerEx(timer, &relative_timeout,
              0,          // no period; the timer is signaled once
              NULL, NULL, // no completion routine
              NULL,       // no wake context; do not resume from suspend
              0))         // no tolerable delay for timer coalescing
        {
            PyErr_SetFromWindowsErr(0);
            goto error;
        }
msg404868 - (view) Author: Benjamin Szőke (Livius) * Date: 2021-10-23 12:31
A similar solution was introduced in VirtualBox some months ago. Soon, i could get back my Windows 10 developing PC and i can try this things.

https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Runtime/r3/win/timer-win.cpp#L312
msg404936 - (view) Author: Dong-hee Na (corona10) * (Python committer) Date: 2021-10-24 16:03
AS-IS:
average:  0.015609736680984497

TO-BE:
average:  2.7387380599975585e-05

Impressive result :)
History
Date User Action Args
2021-10-24 16:03:37corona10setfiles: + bpo-45429.py

messages: + msg404936
2021-10-24 16:01:39corona10setkeywords: + patch
stage: patch review
pull_requests: + pull_request27472
2021-10-23 12:31:54Liviussetmessages: + msg404868
2021-10-23 12:13:49Liviussetnosy: + Livius
2021-10-11 23:26:20eryksunsetnosy: + eryksun
messages: + msg403703
2021-10-11 15:59:48vstinnersetmessages: + msg403659
2021-10-11 14:03:09corona10setnosy: + corona10
2021-10-11 08:38:54vstinnersetmessages: + msg403635
2021-10-11 08:32:14vstinnersetmessages: + msg403634
2021-10-11 08:29:09vstinnersetnosy: + paul.moore, tim.golden, zach.ware, steve.dower
components: + Windows
2021-10-11 08:28:27vstinnercreate