Golang: Managing the Garbage Collector settings

golang garbage collection gc settings gogc gomemlimit

3 min read | by Jordi Prats

In Golang, there are two environment variables that can be used to manage the Garbage Collector in Go: GOGC and GOMEMLIMIT. With these variables, you can control how often the garbage collector runs and set an overall memory limit that the Go runtime can use.

Garbage Collector in Go

To fully understand how to setup the GOGC and GOMEMLIMIT environment variables, it's important to understand how the garbage collector works in Go and it's terminology.

The Go garbage collector is responsible for managing memory allocation and recycling in the heap. The heap is home to dynamically generated objects such as structs, slices, maps, and substantial memory blocks that cannot fit within the stack's constraints. The garbage collector is the tool that it is in change of recycling heap memory and preventing it from growing indefinitely.

From the garbage collector's perspective, the heap memory is divided into two categories: live heap memory and new heap memory:

  • Live heap memory: Memory in use is marked as "live".
  • New heap memory: Is the heap memory yet to be analyzed.

After the garbage collector identifies some unused memory, it reclaims it and makes it available for new memory allocations.

GOGC

The GOGC parameter dictates the percentage of new, unallocated heap memory concerning live memory at which garbage collection initiates. By default, it is set to 100, meaning that garbage collection triggers when the amount of new memory reaches the same amount as the live heap memory.

We can set this value to a lower percertage to trigger the garbage collector more frequently, or to a higher percentage to trigger it less often.

There's a special value for GOGC: off. This value disables triggering the garbage collector due to heap growth.

GOMEMLIMIT

Starting from Go version 1.19, Golang introduced "soft memory management" with the GOMEMLIMIT option. This feature uses the GOMEMLIMIT environment variable to set an overall memory limit that the Go runtime can use.

GOMEMLIMIT can be a double-edged tool: When the overall memory size approaches the GOMEMLIMIT the garbage collector might be constantly triggered, leading to increased CPU usage and decreased program performance. Unlike a OOM error, this can be really tricky to detect and fix.

It is worth mentioning that GOMEMLIMIT doesn't provide a guarantee that the memory limit will be strictly enforced, allowing memory utilization beyond the limit.

Disabling GOGC and setting GOMEMLIMIT

It might be very tempting to set GOGC=off and GOMEMLIMIT to the actual memory limit of the system. We need to keep in mind that the garbage collector is a crucial part of the Go runtime and it's there to keep the memory usage under control: By disabling it and only letting it run when it reaches the memory limit, instead of running small garbage collections, we might end up with a huge garbage collection cycle that will affect the performance of the application.


Posted on 05/11/2024

Categories