Skip to content

Sub-microseconds sleeps on Windows#24

Open
MisterDA wants to merge 1 commit intotrunkfrom
nanonap
Open

Sub-microseconds sleeps on Windows#24
MisterDA wants to merge 1 commit intotrunkfrom
nanonap

Conversation

@MisterDA
Copy link
Owner

@MisterDA MisterDA commented Nov 8, 2023

By using a high-resolution timer, available since Windows 10 RS4
(1803), we can attain sleeps with a 100 nanosecond precision.

A handle representing the high-resolution timer is required for a
thread to sleep. In order to avoid paying the cost of creating and
closing the timer, it is re-set (reused). The timer needs to be stored
somewhere: the domain state is not a good fit as the domain state
cannot be accessed once the runtime system is released, which is
typically the case before a sleep. Moreover, multiple systhreads
belonging to a single domain might want to sleep simultanously.
The systhread structure isn't a good fit either, as runtime threads
don't have access to this. Thread-local storage is a viable option.

Timer handles are created on-demand at the first
caml_win32_nanosleep call of the thread. The first thread entering
this function tests if timer handles can be created at all (with a
PINIT_ONCE, the equivalent of pthread_once), as the feature might
not be supported by the Windows host. Other threads then check if
have_high_resolution_timers is true, and if so, attempt to create
timers.

It seems difficult to precisely know when to close this handle, in
each and every case. To defend against mistakes, we keep a linked list
of these handles. In some cases, threads will close their timer handle
to prevent handle exhaustion when they exit. In the general case, they
will be closed during caml_shutdown.

This commit allows more precision in the platform spin-waits, and also
avoids rounding down quirks: Sleep(0) will put the process at the
end of the process queue, without sleeping.

@MisterDA MisterDA force-pushed the nanonap branch 4 times, most recently from 067ecc3 to 52f5205 Compare June 7, 2024 13:56
@MisterDA MisterDA force-pushed the nanonap branch 7 times, most recently from 2b71830 to a37b22a Compare October 30, 2024 12:40
@MisterDA MisterDA force-pushed the nanonap branch 2 times, most recently from 1802964 to 6fd7306 Compare January 2, 2025 15:39
@MisterDA MisterDA force-pushed the nanonap branch 8 times, most recently from 8a88923 to 38dc0bb Compare January 13, 2025 15:12
@MisterDA MisterDA force-pushed the nanonap branch 2 times, most recently from dd5c20c to e9a1394 Compare January 15, 2025 10:34
@MisterDA MisterDA changed the title Sub-microseconds sleeps on Windows and time cleanups Sub-microseconds sleeps on Windows Jan 24, 2025
@MisterDA MisterDA force-pushed the nanonap branch 3 times, most recently from dc092de to f06e22e Compare January 25, 2025 13:22
By using a high-resolution timer, available since Windows 10 RS4
(1803), we can attain sleeps with a 100 nanosecond precision.

A handle representing the high-resolution timer is required for a
thread to sleep. In order to avoid paying the cost of creating and
closing the timer, it is re-set (reused). The timer needs to be stored
somewhere: the domain state is not a good fit as the domain state
cannot be accessed once the runtime system is released, which is
typically the case before a sleep. Moreover, multiple systhreads
belonging to a single domain might want to sleep simultanously.
The systhread structure isn't a good fit either, as runtime threads
don't have access to this. Thread-local storage is a viable option.

Timer handles are created on-demand at the first
`caml_win32_nanosleep` call of the thread. The first thread entering
this function tests if timer handles can be created at all (with a
`PINIT_ONCE`, the equivalent of `pthread_once`), as the feature might
not be supported by the Windows host. Other threads then check if
`have_high_resolution_timers` is `true`, and if so, attempt to create
timers.

It seems difficult to precisely know when to close this handle, in
each and every case. To defend against mistakes, we keep a linked list
of these handles. In some cases, threads will close their timer handle
to prevent handle exhaustion when they exit. In the general case, they
will be closed during `caml_shutdown`.

This commit allows more precision in the platform spin-waits, and also
avoids rounding down quirks: `Sleep(0)` will put the process at the
end of the process queue, without sleeping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant