aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgc.go
AgeCommit message (Collapse)Author
2021-05-05runtime: implement runqdrain() for GC mark worker goroutinesAndy Pan
Revive CL 310149 Change-Id: Ib4714ea5b2ade32c0f66edff841a79d8212bd79a Reviewed-on: https://go-review.googlesource.com/c/go/+/313009 Run-TryBot: Ian Lance Taylor <iant@golang.org> Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com> Trust: Michael Pratt <mpratt@google.com> Trust: Michael Knyszek <mknyszek@google.com>
2021-04-20Revert "runtime: implement runqdrain() for GC mark worker goroutines"Ian Lance Taylor
This reverts CL 310149. Reason for revert: Breaks longtest builders: https://build.golang.org/log/6af9fb147fa3101154db10e7ce055e8267cd4c93 https://build.golang.org/log/172ed6e1ec3bb503370333ee421c590fd2a72d0a Change-Id: Iaf5a8b9eec51d0517311e050d0b0f7569759d292 Reviewed-on: https://go-review.googlesource.com/c/go/+/312129 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Go Bot <gobot@golang.org>
2021-04-20runtime: implement runqdrain() for GC mark worker goroutinesAndy Pan
Change-Id: Ida44a2e07f277bee8806538ecee4beee3474cf3d Reviewed-on: https://go-review.googlesource.com/c/go/+/310149 Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Trust: Michael Pratt <mpratt@google.com> Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org>
2021-04-16runtime: remove useless nFlushCacheRootsLeonard Wang
Change-Id: I70cb8f8e9a0eec68ea11f22ca8699aa7e0c91ede Reviewed-on: https://go-review.googlesource.com/c/go/+/310710 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Trust: Emmanuel Odeke <emmanuel@orijtech.com>
2021-04-14runtime: pass work.userForced to gcController.endCycle explicitlyMichael Anthony Knyszek
For #44167. Change-Id: I15817006f1870d6237cd06dabad988da3f23a6d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/306604 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-14runtime: move next_gc and last_next_gc into gcControllerStateMichael Anthony Knyszek
This change moves next_gc and last_next_gc into gcControllerState under the names heapGoal and lastHeapGoal respectively. These are fundamentally GC pacer related values, and so it makes sense for them to live here. Partially generated by rf ' ex . { memstats.next_gc -> gcController.heapGoal memstats.last_next_gc -> gcController.lastHeapGoal } ' except for updates to comments and gcControllerState methods, where they're accessed through the receiver, and trace-related renames of NextGC -> HeapGoal, while we're here. For #44167. Change-Id: I1e871ad78a57b01be8d9f71bd662530c84853bed Reviewed-on: https://go-review.googlesource.com/c/go/+/306603 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-14runtime: fix formatting of gcMarkLeonard Wang
Change-Id: I08aed75f3aab0da705544665e532f332adfb075e Reviewed-on: https://go-review.googlesource.com/c/go/+/308949 Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> Trust: David Chase <drchase@google.com>
2021-04-14runtime: move roots' bases calculation to gcMarkRootPrepareRuslan Andreev
This patch provides changes according to Austin's TODO. It just moves calculation of base indexes of each root type from markroot function to gcMarkRootPrepare. Change-Id: Ib231de34e7f81e922762fc3ee2b1830921c0c7cf Reviewed-on: https://go-review.googlesource.com/c/go/+/279461 Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Austin Clements <austin@google.com>
2021-04-14runtime: create initializer for gcControllerStateMichael Anthony Knyszek
Now that gcControllerState contains almost all of the pacer state, create an initializer for it instead of haphazardly setting some fields. For #44167. Change-Id: I4ce1d5dd82003cb7c263fa46697851bb22a32544 Reviewed-on: https://go-review.googlesource.com/c/go/+/306601 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-14runtime: move gcPercent and heapMinimum into gcControllerStateMichael Anthony Knyszek
These variables are core to the pacer, and will be need to be non-global for testing later. Partially generated via rf ' ex . { gcPercent -> gcController.gcPercent heapMinimum -> gcController.heapMinimum } ' The only exception to this generation is usage of these variables in gcControllerState methods. For #44167. Change-Id: I8b620b3061114f3a3c4b65006f715fd977b180a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/306600 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-14runtime: make gcSetTriggerRatio a method of gcControllerStateMichael Anthony Knyszek
gcSetTriggerRatio's purpose is to set a bunch of downstream values when we choose to commit to a new trigger ratio computed by the gcController. Now that almost all the inputs it uses to compute the downstream values are in gcControllerState anyway, make it a method of gcControllerState. For #44167. Change-Id: I1b7ea709e8378566f812ae3450ab169d7fb66aea Reviewed-on: https://go-review.googlesource.com/c/go/+/306599 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-13runtime: move internal GC statistics from memstats to gcControllerMichael Anthony Knyszek
This change moves certain important but internal-only GC statistics from memstats into gcController. These statistics are mainly used in pacing the GC, so it makes sense to keep them in the pacer's state. This CL was mostly generated via rf ' ex . { memstats.gc_trigger -> gcController.trigger memstats.triggerRatio -> gcController.triggerRatio memstats.heap_marked -> gcController.heapMarked memstats.heap_live -> gcController.heapLive memstats.heap_scan -> gcController.heapScan } ' except for a few special cases, like updating names in comments and when these fields are used within gcControllerState methods (at which point they're accessed through the reciever). For #44167. Change-Id: I6bd1602585aeeb80818ded24c07d8e6fec992b93 Reviewed-on: https://go-review.googlesource.com/c/go/+/306598 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-13runtime: rename gcpercent, readgogc, and heapminimum to match Go styleMichael Anthony Knyszek
Generated with: rf 'mv gcpercent gcPercent' rf 'mv readgogc readGOGC' rf 'mv heapminimum heapMinimum' After this, comments referencing these symbols were updated via a simple sed command. For #44167. Change-Id: I6bb01597c2130686c01f967d0f106b06860ad2db Reviewed-on: https://go-review.googlesource.com/c/go/+/306597 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-13runtime: break out GC pacer into its own fileMichael Anthony Knyszek
This change breaks out the GC pacer into its own file so that it'll be easier to see the full implementation and change it. It also suggests an obvious place to put tests (mgcpacer_test.go). This includes all of gcControllerState, gcSetTriggerRatio, anything related to GOGC, and all related globals and constants. This is almost a clean move, except that globals and constants are formatted into blocks instead of having a separate "var" declaration for each one. For #44167. Change-Id: I85aa84ce85c6cfbe0b33e8a3c91cbe9dc41de8cb Reviewed-on: https://go-review.googlesource.com/c/go/+/306596 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2021-04-12runtime: consolidate "is sweep done" conditionsAustin Clements
The runtime currently has two different notions of sweep completion: 1. All spans are either swept or have begun sweeping. 2. The sweeper has *finished* sweeping all spans. Having both is confusing (it doesn't help that the documentation is often unclear or wrong). Condition 2 is stronger and the theoretical slight optimization that condition 1 could impact is never actually useful. Hence, this CL consolidates both conditions down to condition 2. Updates #45315. Change-Id: I55c84d767d74eb31a004a5619eaba2e351162332 Reviewed-on: https://go-review.googlesource.com/c/go/+/307916 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
2021-04-12runtime: block sweep completion on all sweep pathsAustin Clements
The runtime currently has two different notions of sweep completion: 1. All spans are either swept or have begun sweeping. 2. The sweeper has *finished* sweeping all spans. Most things depend on condition 1. Notably, GC correctness depends on condition 1, but since all sweep operations a non-preemptible, the STW at the beginning of GC forces condition 1 to become condition 2. runtime.GC(), however, depends on condition 2, since the intent is to complete a complete GC cycle, and also update the heap profile (which can only be done after sweeping is complete). However, the way we compute condition 2 is racy right now and may in fact only indicate condition 1. Specifically, sweepone blocks condition 2 until all sweepone calls are done, but there are many other ways to enter the sweeper that don't block this. Hence, sweepone may see that there are no more spans in the sweep list and see that it's the last sweepone and declare sweeping done, while there's some other sweeper still working on a span. Fix this by making sure every entry to the sweeper participates in the protocol that blocks condition 2. To make sure we get this right, this CL introduces a type to track sweep blocking and (lightly) enforces span sweep ownership via the type system. This has the nice side-effect of abstracting the pattern of acquiring sweep ownership that's currently repeated in many different places. Fixes #45315. Change-Id: I7fab30170c5ae14c8b2f10998628735b8be6d901 Reviewed-on: https://go-review.googlesource.com/c/go/+/307915 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
2021-04-06runtime: deflake TestGCTestIsReachableAustin Clements
This is a simple workaround for a bug where runtime.GC() can return before finishing a full sweep, causing gcTestIsReachable to throw. The right thing is to fix runtime.GC(), but this should get this test passing reliably in the meantime. Updates #45315. Change-Id: Iae141e6dbb26a9c2649497c1feedd4aaeaf540c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/307809 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org>
2021-04-05runtime: extend internal atomics to comply with sync/atomicRuslan Andreev
The CV add changes according to TODO in Go source-code. Internal atomic set does not comply with sync/atomic library and has shortage operations for signed integers. This patch extend internal atomic set by Int32 and Int64 operations. It's implemented new aliases and asm versions of operations. As a result Cas64 was replaced by Casint64 in findRunnableGCWorker without type casting. Another purpose is unified structure of internal atomics' source code. Before, assembly impementations for different archs were in different files. For example, filename for AMD64 was asm_amd64.s, but filename for RISC-V was atomic_riscv64.s. Some arches have both files without any meaning. So, assembly files were merged and renamed to atomic_{$ARCH}.s filenames. Change-Id: I29a05a7cbf5f4a9cc146e8315536c038af545677 Reviewed-on: https://go-review.googlesource.com/c/go/+/289152 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
2021-04-02runtime: make gcTestMoveStackOnNextCall not double the stackAustin Clements
Currently, gcTestMoveStackOnNextCall doubles the stack allocation on each call because stack movement always doubles the stack. That's rather unfortunate if you're doing a bunch of stack movement tests in a row that don't actually have to grow the stack because you'll quickly hit the stack size limit even though you're hardly using any of the stack. Fix this by adding a special stack poison value for gcTestMoveStackOnNextCall that newstack recognizes and inhibits the allocation doubling. Change-Id: Iace7055a0f33cb48dc97b8f4b46e45304bee832c Reviewed-on: https://go-review.googlesource.com/c/go/+/306672 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org>
2021-04-02runtime: fix TestGCTestMoveStackOnNextCall flakesAustin Clements
gcTestMoveStackOnNextCall can fail to move the stack in very rare cases if there's an unfortunately timed preemption that clobbers the stack guard. This won't happen multiple times in quick succession, so make the test just retry a few times. Change-Id: I247dc0551514e269e7132cee7945291429b0e865 Reviewed-on: https://go-review.googlesource.com/c/go/+/306671 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org>
2021-03-29runtime: add GC testing helpers for regabi signature fuzzerAustin Clements
This CL adds a set of helper functions for testing GC interactions. These are intended for use in the regabi signature fuzzer, but are generally useful for GC tests, so we make them generally available to runtime tests. These provide: 1. An easy way to force stack movement, for testing stack copying. 2. A simple and robust way to check the reachability of a set of pointers. 3. A way to check what general category of memory a pointer points to, mostly so tests can make sure they're testing what they mean to. For #40724, but generally useful. Change-Id: I15d33ccb3f5a792c0472a19c2cc9a8b4a9356a66 Reviewed-on: https://go-review.googlesource.com/c/go/+/305330 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
2021-03-23cmd/compile: wrap/desugar defer calls for register abiThan McIntosh
Adds code to the compiler's "order" phase to rewrite go and defer statements to always be argument-less. E.g. defer f(x,y) => x1, y1 := x, y defer func() { f(x1, y1) } This transformation is not beneficial on its own, but it helps simplify runtime defer handling for the new register ABI (when invoking deferred functions on the panic path, the runtime doesn't need to manage the complexity of determining which args to pass in register vs memory). This feature is currently enabled by default if GOEXPERIMENT=regabi or GOEXPERIMENT=regabidefer is in effect. Included in this CL are some workarounds in the runtime to insure that "go" statement targets in the runtime are argument-less already (since wrapping them can potentially introduce heap-allocated closures, which are currently not allowed). The expectation is that these workarounds will be temporary, and can go away once we either A) change the rules about heap-allocated closures, or B) implement some other scheme for handling go statements. Change-Id: I01060d79a6b140c6f0838d6e6813f807ccdca319 Reviewed-on: https://go-review.googlesource.com/c/go/+/298669 Trust: Than McIntosh <thanm@google.com> Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com>
2021-03-05runtime: encapsulate access to allgsMichael Pratt
Correctly accessing allgs is a bit hairy. Some paths need to lock allglock, some don't. Those that don't are safest using atomicAllG, but usage is not consistent. Rather than doing this ad-hoc, move all access* through forEachG / forEachGRace, the locking and atomic versions, respectively. This will make it easier to ensure safe access. * markroot is the only exception, as it has a far-removed guarantee of safe access via an atomic load of allglen far before actual use. Change-Id: Ie1c7a8243e155ae2b4bc3143577380c695680e89 Reviewed-on: https://go-review.googlesource.com/c/go/+/279994 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>
2021-02-23runtime: clarify GC fractional mode descriptionzhengjianxun
nowdays, in runtime/mgc.go,we can see the comment descrition : The fractional worker is necessary when GOMAXPROCS*gcBackgroundUtilization is not an integer. but it not true such as GOMAXPROCS=5. in the implemet of startCycle() , Fractional Mode happend only when GOMAXPROCS<=3 or GOMAXPROCS=6. so utilization can closest to 25%. Fixes #44380 Change-Id: Id0dd6d9f37759c2c9231f164a013a014216dd442 GitHub-Last-Rev: 5910e76324b2fa908235c325c8b1edafca496256 GitHub-Pull-Request: golang/go#44381 Reviewed-on: https://go-review.googlesource.com/c/go/+/293630 Reviewed-by: Austin Clements <austin@google.com> Trust: Michael Pratt <mpratt@google.com>
2020-10-30runtime: add heap lock assertionsMichael Pratt
Some functions that required holding the heap lock _or_ world stop have been simplified to simply requiring the heap lock. This is conceptually simpler and taking the heap lock during world stop is guaranteed to not contend. This was only done on functions already called on the systemstack to avoid too many extra systemstack calls in GC. Updates #40677 Change-Id: I15aa1dadcdd1a81aac3d2a9ecad6e7d0377befdc Reviewed-on: https://go-review.googlesource.com/c/go/+/250262 Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Trust: Michael Pratt <mpratt@google.com>
2020-10-30runtime: add world-stopped assertionsMichael Pratt
Stopping the world is an implicit lock for many operations, so we should assert the world is stopped in functions that require it. This is enabled along with the rest of lock ranking, though it is a bit orthogonal and likely cheap enough to enable all the time should we choose. Requiring a lock _or_ world stop is common, so that can be expressed as well. Updates #40677 Change-Id: If0a58544f4251d367f73c4120c9d39974c6cd091 Reviewed-on: https://go-review.googlesource.com/c/go/+/248577 Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Trust: Michael Pratt <mpratt@google.com>
2020-10-30runtime: simplify gcBgMarkWorker preemptionMichael Pratt
gcBgMarkWorker G's are primarily scheduled by findRunnableGCWorker, but that no longer needs to be strictly enforced. Temporary preemption to a runq is fine when the P is not in use. We still releasem in gopark in the normal case for efficiency: if gcDrain stops because gp.preempt is set, then gopark would always preempt. That is fine, but inefficient, since it will reschedule simply to park again. Thus, we keep releasem in unlockf to skip this extra cycle. Change-Id: I6d1a42e3ca41b76227142a6b5bfb376c9213e3c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/262349 Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Trust: Michael Pratt <mpratt@google.com>
2020-10-30runtime: manage gcBgMarkWorkers with a global poolMichael Pratt
Background mark workers perform per-P marking work. Currently each worker is assigned a P at creation time. The worker "attaches" to the P via p.gcBgMarkWorker, making itself (usually) available to findRunnableGCWorker for scheduling GC work. While running gcMarkDone, the worker "detaches" from the P (by clearing p.gcBgMarkWorker), since it may park for other reasons and should not be scheduled by findRunnableGCWorker. Unfortunately, this design is complex and difficult to reason about. We simplify things by changing the design to eliminate the hard P attachment. Rather than workers always performing work from the same P, workers perform work for whichever P they find themselves on. On park, the workers are placed in a pool of free workers, which each P's findRunnableGCWorker can use to run a worker for its P. Now if a worker parks in gcMarkDone, a P may simply use another worker from the pool to complete its own work. The P's GC worker mode is used to communicate the mode to run to the selected worker. It is also used to emit the appropriate worker EvGoStart tracepoint. This is a slight change, as this G may be preempted (e.g., in gcMarkDone). When it is rescheduled, the trace viewer will show it as a normal goroutine again. It is currently a bit difficult to connect to the original worker tracepoint, as the viewer does not display the goid for the original worker (though the data is in the trace file). Change-Id: Id7bd3a364dc18a4d2b1c99c4dc4810fae1293c1b Reviewed-on: https://go-review.googlesource.com/c/go/+/262348 Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Trust: Michael Pratt <mpratt@google.com>
2020-10-26runtime,runtime/metrics: add metric for distribution of GC pausesMichael Anthony Knyszek
For #37112. Change-Id: Ibb0425c9c582ae3da3b2662d5bbe830d7df9079c Reviewed-on: https://go-review.googlesource.com/c/go/+/247047 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: rename mcache fields to match Go styleMichael Anthony Knyszek
This change renames a bunch of malloc statistics stored in the mcache that are all named with the "local_" prefix. It also renames largeAlloc to allocLarge to prevent a naming conflict, and next_sample because it would be the last mcache field with the old C naming style. Change-Id: I29695cb83b397a435ede7e9ad5c3c9be72767ea3 Reviewed-on: https://go-review.googlesource.com/c/go/+/246969 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: flush local_scan directly and more oftenMichael Anthony Knyszek
Now that local_scan is the last mcache-based statistic that is flushed by purgecachedstats, and heap_scan and gcController.revise may be interacted with concurrently, we don't need to flush heap_scan at arbitrary locations where the heap is locked, and we don't need purgecachedstats and cachestats anymore. Instead, we can flush local_scan at the same time we update heap_live in refill, so the two updates may share the same revise call. Clean up unused functions, remove code that would cause the heap to get locked in the allocSpan when it didn't need to (other than to flush local_scan), and flush local_scan explicitly in a few important places. Notably we need to flush local_scan whenever we flush the other stats, but it doesn't need to be donated anywhere, so have releaseAll do the flushing. Also, we need to flush local_scan before we set heap_scan at the end of a GC, which was previously handled by cachestats. Just do so explicitly -- it's not much code and it becomes a lot more clear why we need to do so. Change-Id: I35ac081784df7744d515479896a41d530653692d Reviewed-on: https://go-review.googlesource.com/c/go/+/246968 Run-TryBot: Michael Knyszek <mknyszek@google.com> Trust: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: access the assist ratio atomicallyMichael Anthony Knyszek
This change makes it so that the GC assist ratio (the pair of gcControllerState fields assistBytesPerWork and assistWorkPerByte) is updated atomically. Note that the pair of fields are not updated together atomically, but that's OK. The code here was already racy for some time and in practice the assist ratio moves very slowly. The purpose of this change is so that we can document gcController.revise to be safe for concurrent use, which will be useful in further changes. Change-Id: Ie25d630207c88e4f85f2b8953f6a0051ebf1b4ea Reviewed-on: https://go-review.googlesource.com/c/go/+/246963 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: make next_gc atomically accessedMichael Anthony Knyszek
next_gc is mostly updated only during a STW, but may occasionally be updated by calls to e.g. debug.SetGCPercent. In this case the update is supposed to be protected by the heap lock, but in reality it's accessed by gcController.revise which may be called without the heap lock held (despite its documentation, which will be updated in a later change). Change the synchronization policy on next_gc so that it's atomically accessed when the world is not stopped to aid in making revise safe for concurrent use. Change-Id: I79657a72f91563f3241aaeda66e8a7757d399529 Reviewed-on: https://go-review.googlesource.com/c/go/+/246962 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: load gcControllerState.scanWork atomically in reviseMichael Anthony Knyszek
gcControllerState.scanWork's docs state that it must be accessed atomically during a GC cycle, but gcControllerState.revise does not do this (even when called with the heap lock held). This change makes it so that gcControllerState.revise accesses scanWork atomically and explicitly. Note that we don't update gcControllerState.revise's erroneous doc comment here because this change isn't about revise's guarantees, just about heap_scan. The comment is updated in a later change. Change-Id: Iafc3ad214e517190bfd8a219896d23da19f7659d Reviewed-on: https://go-review.googlesource.com/c/go/+/246961 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-26runtime: define and enforce synchronization on heap_scanMichael Anthony Knyszek
Currently heap_scan is mostly protected by the heap lock, but gcControllerState.revise sometimes accesses it without a lock. In an effort to make gcControllerState.revise callable from more contexts (and have its synchronization guarantees actually respected), make heap_scan atomically read from and written to, unless the world is stopped. Note that we don't update gcControllerState.revise's erroneous doc comment here because this change isn't about revise's guarantees, just about heap_scan. The comment is updated in a later change. Change-Id: Iddbbeb954767c704c2bd1d221f36e6c4fc9948a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/246960 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Emmanuel Odeke <emmanuel@orijtech.com> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-10-23runtime: drop redundant gcBlackenEnabled resetMichael Pratt
This reset of gcBlackenEnabled is a no-op because it was already reset almost immediately before in gcMarkDone, which is the only caller of gcMarkTermination. Adjust the comment to clarify setGCPhase a bit more. We are coming from _GCmark, so write barriers are already enabled. Change-Id: Ieac2dadf33c3c5a44e8a25a499dea8cfe03b8d73 Reviewed-on: https://go-review.googlesource.com/c/go/+/241357 Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Michael Pratt <mpratt@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
2020-10-23runtime: drop unused work.ndone fieldMichael Pratt
This field is unused since golang.org/cl/134785 and thus can be trivially removed. Change-Id: I1a87f8e78ffdf662440409404f0251c40bc56a4f Reviewed-on: https://go-review.googlesource.com/c/go/+/241741 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>
2020-10-15runtime: remove debugCachedWorkMichael Pratt
debugCachedWork and all of its dependent fields and code were added to aid in debugging issue #27993. Now that the source of the problem is known and mitigated (via the extra work check after STW in gcMarkDone), these extra checks are no longer required and simply make the code more difficult to follow. Remove it all. Updates #27993 Change-Id: I594beedd5ca61733ba9cc9eaad8f80ea92df1a0d Reviewed-on: https://go-review.googlesource.com/c/go/+/262350 Trust: Michael Pratt <mpratt@google.com> Run-TryBot: Michael Pratt <mpratt@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
2020-08-17runtime: clean up old mcentral codeMichael Anthony Knyszek
This change deletes the old mcentral implementation from the code base and the newMCentralImpl feature flag along with it. Updates #37487. Change-Id: Ibca8f722665f0865051f649ffe699cbdbfdcfcf2 Reviewed-on: https://go-review.googlesource.com/c/go/+/221184 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
2020-08-17runtime: move checkmarks to a separate bitmapAustin Clements
Currently, the GC stores the object marks for checkmarks mode in the heap bitmap using a rather complex encoding: for one word objects, the checkmark is stored in the pointer/scalar bit since one word objects must be pointers; for larger objects, the checkmark is stored in what would be the scan/dead bit for the second word of the object. This encoding made more sense when the runtime used the first scan/dead bit as the regular mark bit, but we moved away from that long ago. This encoding and overloading of the heap bitmap bits causes a great deal of complexity in many parts of the allocator and garbage collector and leads to some subtle bugs like #15903. This CL moves the checkmarks mark bits into their own per-arena bitmap and reclaims the second scan/dead bit as a regular scan/dead bit. I tested this by enabling doubleCheck mode in heapBitsSetType and running in both regular and GODEBUG=gccheckmark=1 mode. Fixes #15903. No performance degradation. (Very slight improvement on a few benchmarks, but it's probably just noise.) name old time/op new time/op delta BiogoIgor 16.6s ± 1% 16.4s ± 1% -0.94% (p=0.000 n=25+24) BiogoKrishna 19.2s ± 3% 19.2s ± 3% ~ (p=0.638 n=23+25) BleveIndexBatch100 6.12s ± 5% 6.17s ± 4% ~ (p=0.170 n=25+25) CompileTemplate 206ms ± 1% 205ms ± 1% -0.43% (p=0.005 n=24+24) CompileUnicode 82.2ms ± 2% 81.5ms ± 2% -0.95% (p=0.001 n=22+22) CompileGoTypes 755ms ± 3% 754ms ± 4% ~ (p=0.715 n=25+25) CompileCompiler 3.73s ± 1% 3.73s ± 1% ~ (p=0.445 n=25+24) CompileSSA 8.67s ± 1% 8.66s ± 1% ~ (p=0.836 n=24+22) CompileFlate 134ms ± 2% 133ms ± 1% -0.66% (p=0.001 n=24+23) CompileGoParser 164ms ± 1% 163ms ± 1% -0.85% (p=0.000 n=24+24) CompileReflect 466ms ± 5% 466ms ± 3% ~ (p=0.863 n=25+25) CompileTar 182ms ± 1% 182ms ± 1% -0.31% (p=0.048 n=24+24) CompileXML 249ms ± 1% 248ms ± 1% -0.32% (p=0.031 n=21+25) CompileStdCmd 10.3s ± 1% 10.3s ± 1% ~ (p=0.459 n=23+23) FoglemanFauxGLRenderRotateBoat 8.66s ± 1% 8.62s ± 1% -0.47% (p=0.000 n=23+24) FoglemanPathTraceRenderGopherIter1 20.3s ± 3% 20.2s ± 2% ~ (p=0.893 n=25+25) GopherLuaKNucleotide 29.7s ± 1% 29.8s ± 2% ~ (p=0.421 n=24+25) MarkdownRenderXHTML 246ms ± 1% 247ms ± 1% ~ (p=0.558 n=25+24) Tile38WithinCircle100kmRequest 779µs ± 4% 779µs ± 3% ~ (p=0.954 n=25+25) Tile38IntersectsCircle100kmRequest 1.02ms ± 3% 1.01ms ± 4% ~ (p=0.658 n=25+25) Tile38KNearestLimit100Request 984µs ± 4% 986µs ± 4% ~ (p=0.627 n=24+25) [Geo mean] 552ms 551ms -0.19% https://perf.golang.org/search?q=upload:20200723.6 Change-Id: Ic703f26a83fb034941dc6f4788fc997d56890dec Reviewed-on: https://go-review.googlesource.com/c/go/+/244539 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Martin Möhrmann <moehrmann@google.com>
2020-04-30runtime: wake scavenger and update address on sweep doneMichael Anthony Knyszek
This change modifies the semantics of waking the scavenger: rather than wake on any update to pacing, wake when we know we will have work to do, that is, when the sweeper is done. The current scavenger runs over the address space just once per GC cycle, and we want to maximize the chance that the scavenger observes the most attractive scavengable memory in that pass (i.e. free memory with the highest address), so the timing is important. By having the scavenger awaken and reset its search space when the sweeper is done, we increase the chance that the scavenger will observe the most attractive scavengable memory, because no more memory will be freed that GC cycle (so the highest scavengable address should now be available). Furthermore, in applications that go idle, this means the background scavenger will be awoken even if another GC doesn't happen, which isn't true today. However, we're unable to wake the scavenger directly from within the sweeper; waking the scavenger involves modifying timers and readying goroutines, the latter of which may trigger an allocation today (and the sweeper may run during allocation!). Instead, we do the following: 1. Set a flag which is checked by sysmon. sysmon will clear the flag and wake the scavenger. 2. Wake the scavenger unconditionally at sweep termination. The idea behind this policy is that it gets us close enough to the state above without having to deal with the complexity of waking the scavenger in deep parts of the runtime. If the application goes idle and sweeping finishes (so we don't reach sweep termination), then sysmon will wake the scavenger. sysmon has a worst-case 20 ms delay in responding to this signal, which is probably fine if the application is completely idle anyway, but if the application is actively allocating, then the proportional sweeper should help ensure that sweeping ends very close to sweep termination, so sweep termination is a perfectly reasonable time to wake up the scavenger. Updates #35788. Change-Id: I84289b37816a7d595d803c72a71b7f5c59d47e6b Reviewed-on: https://go-review.googlesource.com/c/go/+/207998 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
2020-04-27runtime: add new mcentral implementationMichael Anthony Knyszek
Currently mcentral is implemented as a couple of linked lists of spans protected by a lock. Unfortunately this design leads to significant lock contention. The span ownership model is also confusing and complicated. In-use spans jump between being owned by multiple sources, generally some combination of a gcSweepBuf, a concurrent sweeper, an mcentral or an mcache. So first to address contention, this change replaces those linked lists with gcSweepBufs which have an atomic fast path. Then, we change up the ownership model: a span may be simultaneously owned only by an mcentral and the page reclaimer. Otherwise, an mcentral (which now consists of sweep bufs), a sweeper, or an mcache are the sole owners of a span at any given time. This dramatically simplifies reasoning about span ownership in the runtime. As a result of this new ownership model, sweeping is now driven by walking over the mcentrals rather than having its own global list of spans. Because we no longer have a global list and we traditionally haven't used the mcentrals for large object spans, we no longer have anywhere to put large objects. So, this change also makes it so that we keep large object spans in the appropriate mcentral lists. In terms of the static lock ranking, we add the spanSet spine locks in pretty much the same place as the mcentral locks, since they have the potential to be manipulated both on the allocation and sweep paths, like the mcentral locks. This new implementation is turned on by default via a feature flag called go115NewMCentralImpl. Benchmark results for 1 KiB allocation throughput (5 runs each): name \ MiB/s go113 go114 gotip gotip+this-patch AllocKiB-1 1.71k ± 1% 1.68k ± 1% 1.59k ± 2% 1.71k ± 1% AllocKiB-2 2.46k ± 1% 2.51k ± 1% 2.54k ± 1% 2.93k ± 1% AllocKiB-4 4.27k ± 1% 4.41k ± 2% 4.33k ± 1% 5.01k ± 2% AllocKiB-8 4.38k ± 3% 5.24k ± 1% 5.46k ± 1% 8.23k ± 1% AllocKiB-12 4.38k ± 3% 4.49k ± 1% 5.10k ± 1% 10.04k ± 0% AllocKiB-16 4.31k ± 1% 4.14k ± 3% 4.22k ± 0% 10.42k ± 0% AllocKiB-20 4.26k ± 1% 3.98k ± 1% 4.09k ± 1% 10.46k ± 3% AllocKiB-24 4.20k ± 1% 3.97k ± 1% 4.06k ± 1% 10.74k ± 1% AllocKiB-28 4.15k ± 0% 4.00k ± 0% 4.20k ± 0% 10.76k ± 1% Fixes #37487. Change-Id: I92d47355acacf9af2c41bf080c08a8c1638ba210 Reviewed-on: https://go-review.googlesource.com/c/go/+/221182 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
2020-04-16runtime: prevent preemption while releasing worldsema in gcStartMichael Anthony Knyszek
Currently, as a result of us releasing worldsema now to allow STW events during a mark phase, we release worldsema between starting the world and having the goroutine block in STW mode. This inserts preemption points which, if followed through, could lead to a deadlock. Specifically, because user goroutine scheduling is disabled in STW mode, the goroutine will block before properly releasing worldsema. The fix here is to prevent preemption while releasing the worldsema. Fixes #38404. Updates #19812. Change-Id: I8ed5b3aa108ab2e4680c38e77b0584fb75690e3d Reviewed-on: https://go-review.googlesource.com/c/go/+/228337 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Austin Clements <austin@google.com>
2020-04-07runtime: static lock ranking for the runtime (enabled by GOEXPERIMENT)Dan Scales
I took some of the infrastructure from Austin's lock logging CR https://go-review.googlesource.com/c/go/+/192704 (with deadlock detection from the logs), and developed a setup to give static lock ranking for runtime locks. Static lock ranking establishes a documented total ordering among locks, and then reports an error if the total order is violated. This can happen if a deadlock happens (by acquiring a sequence of locks in different orders), or if just one side of a possible deadlock happens. Lock ordering deadlocks cannot happen as long as the lock ordering is followed. Along the way, I found a deadlock involving the new timer code, which Ian fixed via https://go-review.googlesource.com/c/go/+/207348, as well as two other potential deadlocks. See the constants at the top of runtime/lockrank.go to show the static lock ranking that I ended up with, along with some comments. This is great documentation of the current intended lock ordering when acquiring multiple locks in the runtime. I also added an array lockPartialOrder[] which shows and enforces the current partial ordering among locks (which is embedded within the total ordering). This is more specific about the dependencies among locks. I don't try to check the ranking within a lock class with multiple locks that can be acquired at the same time (i.e. check the ranking when multiple hchan locks are acquired). Currently, I am doing a lockInit() call to set the lock rank of most locks. Any lock that is not otherwise initialized is assumed to be a leaf lock (a very high rank lock), so that eliminates the need to do anything for a bunch of locks (including all architecture-dependent locks). For two locks, root.lock and notifyList.lock (only in the runtime/sema.go file), it is not as easy to do lock initialization, so instead, I am passing the lock rank with the lock calls. For Windows compilation, I needed to increase the StackGuard size from 896 to 928 because of the new lock-rank checking functions. Checking of the static lock ranking is enabled by setting GOEXPERIMENT=staticlockranking before doing a run. To make sure that the static lock ranking code has no overhead in memory or CPU when not enabled by GOEXPERIMENT, I changed 'go build/install' so that it defines a build tag (with the same name) whenever any experiment has been baked into the toolchain (by checking Expstring()). This allows me to avoid increasing the size of the 'mutex' type when static lock ranking is not enabled. Fixes #38029 Change-Id: I154217ff307c47051f8dae9c2a03b53081acd83a Reviewed-on: https://go-review.googlesource.com/c/go/+/207619 Reviewed-by: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-26runtime: ensure minTriggerRatio never exceeds maxTriggerRatioMichael Anthony Knyszek
Currently, the capping logic for the GC trigger ratio is such that if gcpercent is low, we may end up setting the trigger ratio far too high, breaking the promise of SetGCPercent and GOGC has a trade-off knob (we won't start a GC early enough, and we will use more memory). This change modifies the capping logic for the trigger ratio by scaling the minTriggerRatio with gcpercent the same way we scale maxTriggerRatio. Fixes #37927. Change-Id: I2a048c1808fb67186333d3d5a6bee328be2f35da Reviewed-on: https://go-review.googlesource.com/c/go/+/223937 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
2020-03-18runtime: don't hold worldsema across mark phaseMichael Anthony Knyszek
This change makes it so that worldsema isn't held across the mark phase. This means that various operations like ReadMemStats may now stop the world during the mark phase, reducing latency on such operations. Only three such operations are still no longer allowed to occur during marking: GOMAXPROCS, StartTrace, and StopTrace. For the former it's because any change to GOMAXPROCS impacts GC mark background worker scheduling and the details there are tricky. For the latter two it's because tracing needs to observe consistent GC start and GC end events, and if StartTrace or StopTrace may stop the world during marking, then it's possible for it to see a GC end event without a start or GC start event without an end, respectively. To ensure that GOMAXPROCS and StartTrace/StopTrace cannot proceed until marking is complete, the runtime now holds a new semaphore, gcsema, across the mark phase just like it used to with worldsema. This change is being landed once more after being reverted in the Go 1.14 release cycle, since CL 215157 allows it to have a positive effect on system performance. For the benchmark BenchmarkReadMemStatsLatency in the runtime, which measures ReadMemStats latencies while the GC is exercised, the tail of these latencies reduced dramatically on an 8-core machine: name old 50%tile-ns new 50%tile-ns delta ReadMemStatsLatency-8 4.40M ±74% 0.12M ± 2% -97.35% (p=0.008 n=5+5) name old 90%tile-ns new 90%tile-ns delta ReadMemStatsLatency-8 102M ± 6% 0M ±14% -99.79% (p=0.008 n=5+5) name old 99%tile-ns new 99%tile-ns delta ReadMemStatsLatency-8 147M ±18% 4M ±57% -97.43% (p=0.008 n=5+5) Fixes #19812. Change-Id: If66c3c97d171524ae29f0e7af4bd33509d9fd0bb Reviewed-on: https://go-review.googlesource.com/c/go/+/216557 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-01-24Revert "runtime: don't hold worldsema across mark phase"Michael Knyszek
This reverts commit 7b294cdd8df0a9523010f6ffc80c59e64578f34b, CL 182657. Reason for revert: This change may be causing latency problems for applications which call ReadMemStats, because it may cause all goroutines to stop until the GC completes. https://golang.org/cl/215157 fixes this problem, but it's too late in the cycle to land that. Updates #19812. Change-Id: Iaa26f4dec9b06b9db2a771a44e45f58d0aa8f26d Reviewed-on: https://go-review.googlesource.com/c/go/+/216358 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-01-24Revert "runtime: release worldsema before Gosched in STW GC mode"Michael Knyszek
This reverts commit 05511a5c0ae238325c10b0e4e44c3f66f928e4cf, CL 208379. Reason for revert: So that we can cleanly revert https://golang.org/cl/182657. Change-Id: I4fdf4f864a093db7866b3306f0f8f856b9f4d684 Reviewed-on: https://go-review.googlesource.com/c/go/+/216357 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-11-22runtime: release worldsema before Gosched in STW GC modeMichael Anthony Knyszek
After CL 182657 we no longer hold worldsema across the GC, we hold gcsema instead. However in STW GC mode we don't release worldsema before calling Gosched on the user goroutine (note that user goroutines are disabled during STW GC) so that user goroutine holds onto it. When the GC is done and the runtime inevitably wants to "stop the world" again (though there isn't much to stop) it'll sit there waiting for worldsema which won't be released until the aforementioned goroutine is scheduled, which it won't be until the GC is done! So, we have a deadlock. The fix is easy: just release worldsema before calling Gosched. Fixes #34736. Change-Id: Ia50db22ebed3176114e7e60a7edaf82f8535c1b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/208379 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-11-08runtime: make more page sweeper operations atomicMichael Anthony Knyszek
This change makes it so that allocation and free related page sweeper metadata operations (e.g. pageInUse and pagesInUse) are atomic rather than protected by the heap lock. This will help in reducing the length of the critical path with the heap lock held in future changes. Updates #35112. Change-Id: Ie82bff024204dd17c4c671af63350a7a41add354 Reviewed-on: https://go-review.googlesource.com/c/go/+/196640 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>