ecfce58965
When an M transitions from spinning to non-spinning state, it must recheck most sources of work to avoid missing work submitted between its initial check and decrementing sched.nmspinning (see "delicate dance" comment). Ever since the scheduler rewrite in Go 1.1 (golang.org/cl/7314062), we have performed this recheck on all Ms before stopping, regardless of whether or not they were spinning. Unfortunately, there is a problem with this approach: non-spinning Ms are not eligible to steal work (note the skip over the stealWork block), but can detect work during the recheck. If there is work available, this non-spinning M will jump to top, skip stealing, land in recheck again, and repeat. i.e., it will spin uselessly. The spin is bounded. This can only occur if there is another spinning M, which will either take the work, allowing this M to stop, or take some other work, allowing this M to upgrade to spinning. But the spinning is ultimately just a fancy spin-wait. golang.org/issue/43997 discusses several ways to address this. This CL takes the simplest approach: skipping the recheck on non-spinning Ms and allowing them to go to stop. Results for scheduler-relevant runtime and time benchmarks can be found at https://perf.golang.org/search?q=upload:20210420.5. The new BenchmarkCreateGoroutinesSingle is a characteristic example workload that hits this issue hard. A single M readies lots of work without itself parking. Other Ms must spin to steal work, which is very short-lived, forcing those Ms to spin again. Some of the Ms will be non-spinning and hit the above bug. With this fixed, that benchmark drops in CPU usage by a massive 68%, and wall time 24%. BenchmarkNetpollBreak shows similar drops because it is unintentionally almost the same benchmark (create short-living Gs in a loop). Typical well-behaved programs show little change. We also measure scheduling latency (time from goready to execute). Note that many of these benchmarks are very noisy because they don't involve much scheduling. Those that do, like CreateGoroutinesSingle, are expected to increase as we are replacing unintentional spin waiting with a real park. Fixes #43997 Change-Id: Ie1d1e1800f393cee1792455412caaa5865d13562 Reviewed-on: https://go-review.googlesource.com/c/go/+/310850 Trust: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> |
||
---|---|---|
.github | ||
api | ||
doc | ||
lib/time | ||
misc | ||
src | ||
test | ||
.gitattributes | ||
.gitignore | ||
AUTHORS | ||
codereview.cfg | ||
CONTRIBUTING.md | ||
CONTRIBUTORS | ||
LICENSE | ||
PATENTS | ||
README.md | ||
SECURITY.md |
The Go Programming Language
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.
Gopher image by Renee French, licensed under Creative Commons 3.0 Attributions license.
Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.
Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.
Download and Install
Binary Distributions
Official binary distributions are available at https://golang.org/dl/.
After downloading a binary release, visit https://golang.org/doc/install for installation instructions.
Install From Source
If a binary distribution is not available for your combination of operating system and architecture, visit https://golang.org/doc/install/source for source installation instructions.
Contributing
Go is the work of thousands of contributors. We appreciate your help!
To contribute, please read the contribution guidelines at https://golang.org/doc/contribute.html.
Note that the Go project uses the issue tracker for bug reports and proposals only. See https://golang.org/wiki/Questions for a list of places to ask questions about the Go language.