runtime: recompute timer channel send delay at send time - #80894
runtime: recompute timer channel send delay at send time#80894dniminenn wants to merge 1 commit into
Conversation
The timer struct documents the delay argument as nanotime() - t.when. time.sendTime uses it to reconstruct the delivered value as Now().Add(-delta). unlockAndRun computes delta from the now cached by the caller. The heap update, the sendLock acquisition, other timers due in the same timers.run pass, and preemption of the timer-running M all happen after that clock read. Their duration lands in the delivered value as one-sided, load-dependent error. The common case is a few hundred nanoseconds. Under scheduler or interrupt pressure the error reaches several microseconds. Consumers that bin ticker values against a wall-clock grid see the outliers as phantom missed ticks. A value that crosses a period boundary makes floor arithmetic count two elapsed periods where one elapsed. Recompute delta immediately before the send. This matches its documented definition at the moment of use, and the reconstruction then recovers the fire time to within two adjacent clock reads. Measured on linux/amd64 (i5-8500, idle), the mean error of 1s ticker values against the scheduled grid drops from ~600ns with one-sided tails beyond 1.4us to 0ns +/- 0.5us with no observed tails. The cost is one nanotime call per channel-timer firing. Synctest bubbles keep their fake-clock delta. Fixes golang#80893
|
This PR (HEAD: 69e386c) has been imported to Gerrit for code review. Please visit Gerrit at https://go-review.googlesource.com/c/go/+/815940. Important tips:
|
|
Message from Gopher Robot: Patch Set 1: Congratulations on opening your first change. Thank you for your contribution! Next steps: Most changes in the Go project go through a few rounds of revision. This can be During May-July and Nov-Jan the Go project is in a code freeze, during which Please don’t reply on this GitHub thread. Visit golang.org/cl/815940. |
|
Message from Ian Lance Taylor: Patch Set 1: (1 comment) Please don’t reply on this GitHub thread. Visit golang.org/cl/815940. |
|
Message from jl: Patch Set 2: (2 comments) Please don’t reply on this GitHub thread. Visit golang.org/cl/815940. |
time.sendTime reconstructs the delivered value as Now().Add(-delta),
but unlockAndRun computes delta from a cached clock read, so the work
between that read and the send lands in the delivered value as
one-sided, load-dependent error. Recompute delta immediately before
the send, matching its documented definition, nanotime() - t.when, at
the moment of use.
Fixes #80893