Since go1.14, cpu busy goroutine will not occupy a P indefinitely any more. This is done by a cool feature: asynchronously preemption. There is one extra NoP thread(sysmon) runs time to time. It checks if current goroutine has run 10+ms. If so, signal the M runs this goroutine to switch to another goroutine. The function calling graph looks like this: sysmon() { for { usleep(delay) retake() { if schedwhen + 10ms <= now { preemptone() } } } } schedwhen is the time when the goroutine was scheduled to use cpu. So I conclude that Go prevents goroutine from running more than 10ms. However, My local cpu-bound test shows almost all goroutine run 10+ms successively. It seems avg 20ms. See attachments for test code and trace.
The reason is usleep(delay). Preemption checking happens every 10ms. this is a less frequent sampling rate. To achieve 10ms time slice, the checking should happens less than every 5ms. For example, background forcegc goroutine does check gcTrigger every forcegcperiod/2 to guarantee that GC happens at least once every forcegcperiod. How long a goroutine could run by design? If its 10ms, sysmon should sleep less than 5ms. If its 20ms, forecePreemptNs should be doubled. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/1c9d3998-173c-44fa-b69f-32650186d139n%40googlegroups.com.
trace.out
Description: Binary data
preempt_test.go
Description: Binary data