从源码看Golang的垃圾回收机制， 基于Golang 1.15.3版本。
Copyright 2009 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 【一些版权相关的解释】 Garbage collector (GC). 【垃圾回收】 The GC runs concurrently with mutator threads, is type accurate (aka precise), allows multiple GC thread to run in parallel. It is a concurrent mark and sweep that uses a write barrier. It is non-generational and non-compacting. Allocation is done using size segregated per P allocation areas to minimize fragmentation while eliminating locks in the common case. 【GC与mutator线程同时运行，类型准确（也称为精确），允许多个GC线程并行运行。 它是使用写入屏障的**并发标记和清除CMS**。 它是非代际和紧凑的。 使用每个P分配区域隔离的大小来完成分配，以最大程度地减少碎片，同时消除常见情况下的锁定。】 The algorithm decomposes into several steps. This is a high level description of the algorithm being used. For an overview of GC a good place to start is Richard Jones' gchandbook.org. The algorithm's intellectual heritage includes Dijkstra's on-the-fly algorithm, see Edsger W. Dijkstra, Leslie Lamport, A. J. Martin, C. S. Scholten, and E. F. M. Steffens. 1978. On-the-fly garbage collection: an exercise in cooperation. Commun. ACM 21, 11 (November 1978), 966-975. For journal quality proofs that these steps are complete, correct, and terminate see Hudson, R., and Moss, J.E.B. Copying Garbage Collection without stopping the world. Concurrency and Computation: Practice and Experience 15(3-5), 2003. 1. GC performs sweep termination. a. Stop the world. This causes all Ps to reach a GC safe-point. b. Sweep any unswept spans. There will only be unswept spans if this GC cycle was forced before the expected time. 2. GC performs the mark phase. a. Prepare for the mark phase by setting gcphase to _GCmark (from _GCoff), enabling the write barrier, enabling mutator assists, and enqueueing root mark jobs. No objects may be scanned until all Ps have enabled the write barrier, which is accomplished using STW. b. Start the world. From this point, GC work is done by mark workers started by the scheduler and by assists performed as part of allocation. The write barrier shades both the overwritten pointer and the new pointer value for any pointer writes (see mbarrier.go for details). Newly allocated objects are immediately marked black. c. GC performs root marking jobs. This includes scanning all stacks, shading all globals, and shading any heap pointers in off-heap runtime data structures. Scanning a stack stops a goroutine, shades any pointers found on its stack, and then resumes the goroutine. d. GC drains the work queue of grey objects, scanning each grey object to black and shading all pointers found in the object (which in turn may add those pointers to the work queue). e. Because GC work is spread across local caches, GC uses a distributed termination algorithm to detect when there are no more root marking jobs or grey objects (see gcMarkDone). At this point, GC transitions to mark termination. 3. GC performs mark termination. a. Stop the world. b. Set gcphase to _GCmarktermination, and disable workers and assists. c. Perform housekeeping like flushing mcaches. 4. GC performs the sweep phase. a. Prepare for the sweep phase by setting gcphase to _GCoff, setting up sweep state and disabling the write barrier. b. Start the world. From this point on, newly allocated objects are white, and allocating sweeps spans before use if necessary. c. GC does concurrent sweeping in the background and in response to allocation. See description below. 5. When sufficient allocation has taken place, replay the sequence starting with 1 above. See discussion of GC rate below. Concurrent sweep. The sweep phase proceeds concurrently with normal program execution. The heap is swept span-by-span both lazily (when a goroutine needs another span) and concurrently in a background goroutine (this helps programs that are not CPU bound). At the end of STW mark termination all spans are marked as "needs sweeping". The background sweeper goroutine simply sweeps spans one-by-one. To avoid requesting more OS memory while there are unswept spans, when a goroutine needs another span, it first attempts to reclaim that much memory by sweeping. When a goroutine needs to allocate a new small-object span, it sweeps small-object spans for the same object size until it frees at least one object. When a goroutine needs to allocate large-object span from heap, it sweeps spans until it frees at least that many pages into heap. There is one case where this may not suffice: if a goroutine sweeps and frees two nonadjacent one-page spans to the heap, it will allocate a new two-page span, but there can still be other one-page unswept spans which could be combined into a two-page span. It's critical to ensure that no operations proceed on unswept spans (that would corrupt mark bits in GC bitmap). During GC all mcaches are flushed into the central cache, so they are empty. When a goroutine grabs a new span into mcache, it sweeps it. When a goroutine explicitly frees an object or sets a finalizer, it ensures that the span is swept (either by sweeping it, or by waiting for the concurrent sweep to finish). The finalizer goroutine is kicked off only when all spans are swept. When the next GC starts, it sweeps all not-yet-swept spans (if any). GC rate. Next GC is after we've allocated an extra amount of memory proportional to the amount already in use. The proportion is controlled by GOGC environment variable (100 by default). If GOGC=100 and we're using 4M, we'll GC again when we get to 8M (this mark is tracked in next_gc variable). This keeps the GC cost in linear proportion to the allocation cost. Adjusting GOGC just changes the linear constant (and also the amount of extra memory used). Oblets In order to prevent long pauses while scanning large objects and to improve parallelism, the garbage collector breaks up scan jobs for objects larger than maxObletBytes into "oblets" of at most maxObletBytes. When scanning encounters the beginning of a large object, it scans only the first oblet and enqueues the remaining oblets as new scan jobs.