github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/go15gc.article (about)

     1  Go GC: Prioritizing low latency and simplicity
     2  31 Aug 2015
     3  
     4  Richard Hudson
     5  rlh@golang.org
     6  
     7  * The Setup
     8  
     9  Go is building a garbage collector (GC) not only for 2015 but for 2025 and
    10  beyond: A GC that supports today’s software development and scales along with
    11  new software and hardware throughout the next decade. Such a future has no
    12  place for stop-the-world GC pauses, which have been an impediment to broader
    13  uses of safe and secure languages such as Go.
    14  
    15  Go 1.5, the first glimpse of this future, achieves GC latencies well below the
    16  10 millisecond goal we set a year ago. We presented some impressive numbers
    17  in [[https://talks.golang.org/2015/go-gc.pdf][a talk at Gophercon]].
    18  The latency improvements have generated a lot of attention;
    19  Robin Verlangen’s blog post
    20  [[https://medium.com/@robin.verlangen/billions-of-request-per-day-meet-go-1-5-362bfefa0911][_Billions_of_requests_per_day_meet_Go_1.5_]]
    21  validates our direction with end to end results.
    22  We also particularly enjoyed
    23  [[https://twitter.com/inconshreveable/status/620650786662555648][Alan Shreve’s production server graphs]]
    24  and his "Holy 85% reduction" comment.
    25  
    26  Today 16 gigabytes of RAM costs $100 and CPUs come with many cores, each with
    27  multiple hardware threads. In a decade this hardware will seem quaint but the
    28  software being built in Go today will need to scale to meet expanding needs and
    29  the next big thing. Given that hardware will provide the power to increase
    30  throughput, Go’s garbage collector is being designed to favor low latency and
    31  tuning via only a single knob. Go 1.5 is the first big step down this path and
    32  these first steps will forever influence Go and the applications it best
    33  supports. This blog post gives a high-level overview of what we have done for
    34  the Go 1.5 collector.
    35  
    36  * The Embellishment
    37  
    38  To create a garbage collector for the next decade, we turned to an algorithm
    39  from decades ago. Go's new garbage collector is a _concurrent_, _tri-color_,
    40  _mark-sweep_ collector, an idea first proposed by
    41  [[http://dl.acm.org/citation.cfm?id=359655][Dijkstra in 1978]].
    42  This is a deliberate divergence from most "enterprise" grade garbage collectors
    43  of today, and one that we believe is well suited to the properties of modern
    44  hardware and the latency requirements of modern software.
    45  
    46  In a tri-color collector, every object is either white, grey, or black and we
    47  view the heap as a graph of connected objects. At the start of a GC cycle all
    48  objects are white. The GC visits all _roots_, which are objects directly
    49  accessible by the application such as globals and things on the stack, and
    50  colors these grey. The GC then chooses a grey object, blackens it, and then
    51  scans it for pointers to other objects. When this scan finds a pointer to a
    52  white object, it turns that object grey. This process repeats until there are
    53  no more grey objects. At this point, white objects are known to be unreachable
    54  and can be reused.
    55  
    56  This all happens concurrently with the application, known as the _mutator_,
    57  changing pointers while the collector is running. Hence, the mutator must
    58  maintain the invariant that no black object points to a white object, lest the
    59  garbage collector lose track of an object installed in a part of the heap it
    60  has already visited. Maintaining this invariant is the job of the
    61  _write_barrier_, which is a small function run by the mutator whenever a
    62  pointer in the heap is modified. Go’s write barrier colors the now-reachable
    63  object grey if it is currently white, ensuring that the garbage collector will
    64  eventually scan it for pointers.
    65  
    66  Deciding when the job of finding all grey objects is done is subtle and can be
    67  expensive and complicated if we want to avoid blocking the mutators. To keep
    68  things simple Go 1.5 does as much work as it can concurrently and then briefly
    69  stops the world to inspect all potential sources of grey objects. Finding the
    70  sweet spot between the time needed for this final stop-the-world and the total
    71  amount of work that this GC does is a major deliverable for Go 1.6.
    72  
    73  Of course the devil is in the details. When do we start a GC cycle? What
    74  metrics do we use to make that decision? How should the GC interact with the Go
    75  scheduler? How do we pause a mutator thread long enough to scan its stack?
    76   How do we represent white, grey, and black so we can efficiently find and scan
    77  grey objects? How do we know where the roots are? How do we know where in an
    78  object pointers are located? How do we minimize memory fragmentation? How do we
    79  deal with cache performance issues? How big should the heap be? And on and on,
    80  some related to allocation, some to finding reachable objects, some related to
    81  scheduling, but many related to performance. Low-level discussions of each of
    82  these areas are beyond the scope of this blog post.
    83  
    84  At a higher level, one approach to solving performance problems is to add GC
    85  knobs, one for each performance issue. The programmer can then turn the knobs
    86  in search of appropriate settings for their application. The downside is that
    87  after a decade with one or two new knobs each year you end up with the GC Knobs
    88  Turner Employment Act. Go is not going down that path. Instead we provide a
    89  single knob, called GOGC. This value controls the total size of the heap
    90  relative to the size of reachable objects. The default value of 100 means that
    91  total heap size is now 100% bigger than (i.e., twice) the size of the reachable
    92  objects after the last collection. 200 means total heap size is 200% bigger
    93  than (i.e., three times) the size of the reachable objects. If you want to
    94  lower the total time spent in GC, increase GOGC. If you want to trade more GC
    95  time for less memory, lower GOGC.
    96  
    97  More importantly as RAM doubles with the next generation of hardware, simply
    98  doubling GOGC will halve the number of GC cycles. On the other hand since GOGC
    99  is based on reachable object size, doubling the load by doubling the reachable
   100  objects requires no retuning. The application just scales.
   101  Furthermore, unencumbered by ongoing support for dozens of knobs, the runtime
   102  team can focus on improving the runtime based on feedback from real customer
   103  applications.
   104  
   105  * The Punchline
   106  
   107  Go 1.5’s GC ushers in a future where stop-the-world pauses are no longer a
   108  barrier to moving to a safe and secure language. It is a future where
   109  applications scale effortlessly along with hardware and as hardware becomes
   110  more powerful the GC will not be an impediment to better, more scalable
   111  software. It’s a good place to be for the next decade and beyond.
   112  For more details about the 1.5 GC and how we eliminated latency issues see the
   113  [[https://www.youtube.com/watch?v=aiv1JOfMjm0][Go GC: Latency Problem Solved presentation]]
   114  or [[https://talks.golang.org/2015/go-gc.pdf][the slides]].