You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On macOS pre-Catalina we see that in some cases std::steady_clock::now() either reverses or does not advance after the system resumes from sleep. I cannot reproduce this effect on Catalina.
I speculate that pre-Catalina CLOCK_UPTIME_RAW was very close to the raw output of the RDTSC instruction and is therefore reset to zero in some "deeper" sleep states where the CPUs are powered-down. The circumstantial evidence for this is that we were never able to reproduce the issue with short periods of sleep on macs that are plugged in to an electricity supply, whereas it occurred most often in the wild on Monday mornings when people open laptop lids after the weekend.
I'm reporting it here because it seems to me that the current implementation of std::steady_clock does not meet the standard's requirement that it should "advance at a steady rate relative to real time" at least on macOS Mojave.
Workaround
We have addressed this in our application by providing our own steady_clock that's based on CLOCK_MONOTONIC_RAW.
Proposed Fix
I leave it to the libc++ team to decide whether to make a similar change to the standard library - I appreciate that it's a difficult balance given the precision concerns mentioned in https://reviews.llvm.org/D27429
Testing CLOCK_MONOTONIC_RAW on Catalina I do not encounter repeating timestamps at nanosecond resolution so it appears that Apple have addressed that concern mentioned in D27429.
Application-level Symptoms
In our application this manifested in a few ways. The most-obvious was very high CPU usage after resume. When we grabbed a CPU profile it showed that we were burning time in the spinning part of a hybrid lock - it tries to spin for 5 microseconds before suspending. Because std::steady_clock::now() was not advancing it did not ever meet the condition to stop spinning.
We also saw this as bugs where scheduled work was not happening after the desired time in our work scheduler; it would happen much later if at all.
The text was updated successfully, but these errors were encountered:
I'm somewhat wondering why CLOCK_MONOTONIC_RAW wasn't used in the first place in D27429. It was mentioned, but nobody explained why it wasn't a suitable implementation instead of CLOCK_UPTIME_RAW.
commit 8bec8927134f116eb11ddea9db78b1a6241884c9
Author: Louis Dionne <ldionne@apple.com>
Date: Mon Feb 10 18:30:43 2020 +0100
[libc++][Apple] Use CLOCK_MONOTONIC_RAW instead of CLOCK_UPTIME_RAW for steady_clock
Summary:
In D27429, we switched the Apple implementation of steady_clock::now()
from clock_gettime(CLOCK_MONOTONIC) to clock_gettime(CLOCK_UPTIME_RAW).
The purpose was to get nanosecond precision, and also to improve the
performance of the implementation.
However, it appears that CLOCK_UPTIME_RAW does not satisfy the requirements
of the Standard, since it is not strictly speaking monotonic. Indeed, the
clock does not increment while the system is asleep, which had been
mentioned in D27429 but somehow not addressed.
This patch switches to CLOCK_MONOTONIC_RAW, which is monotonic, increased
during sleep, and also has nanosecond precision.
llvm/llvm-project#44118
Extended Description
On macOS pre-Catalina we see that in some cases std::steady_clock::now() either reverses or does not advance after the system resumes from sleep. I cannot reproduce this effect on Catalina.
I speculate that pre-Catalina CLOCK_UPTIME_RAW was very close to the raw output of the
RDTSC
instruction and is therefore reset to zero in some "deeper" sleep states where the CPUs are powered-down. The circumstantial evidence for this is that we were never able to reproduce the issue with short periods of sleep on macs that are plugged in to an electricity supply, whereas it occurred most often in the wild on Monday mornings when people open laptop lids after the weekend.I'm reporting it here because it seems to me that the current implementation of std::steady_clock does not meet the standard's requirement that it should "advance at a steady rate relative to real time" at least on macOS Mojave.
Workaround
We have addressed this in our application by providing our own steady_clock that's based on CLOCK_MONOTONIC_RAW.
Proposed Fix
I leave it to the libc++ team to decide whether to make a similar change to the standard library - I appreciate that it's a difficult balance given the precision concerns mentioned in https://reviews.llvm.org/D27429
Testing CLOCK_MONOTONIC_RAW on Catalina I do not encounter repeating timestamps at nanosecond resolution so it appears that Apple have addressed that concern mentioned in D27429.
Application-level Symptoms
In our application this manifested in a few ways. The most-obvious was very high CPU usage after resume. When we grabbed a CPU profile it showed that we were burning time in the spinning part of a hybrid lock - it tries to spin for 5 microseconds before suspending. Because
std::steady_clock::now()
was not advancing it did not ever meet the condition to stop spinning.We also saw this as bugs where scheduled work was not happening after the desired time in our work scheduler; it would happen much later if at all.
The text was updated successfully, but these errors were encountered: