Summary:

“Improved” in quotes, because the community feedback was so problematic that it did more harm than good, so Go 1.16 was changed back…

Questions include, but are not limited to:

  • Cause user experience problems: Go Issues often occur when you think memory leaks are not met and memory is not released immediately.

  • Confusing statistics with monitoring tools: on Grafana and other monitors, the container process was found to have high memory and slow release, causing an alarm.

  • This results in poor integration of individual management systems associated with memory usage: for example, Kubernetes HPA, or patterns such as custom scaling policies that are difficult to evaluate.

  • Squeeze other applications on the same host: Not all Go applications must run independently on a single host, which naturally squeezes other applications on the same host, which is difficult to evaluate.

(See new Go1.16 feature: Detailed Memory Management Changes you need to know)

This problem occurs when the Go version is between 1.12 and 1.15 (both are closed interval), the Linux system and the kernel version is >=4.5

To disable this function, set the environment variable GODEBUG: madvdontNeed =1

Go to Go 1.15 1.12

Go supports two memory reclamation methods: MADV_DONTNEED and MADV_FREE

The MADV_FREE is

Go to 1.12

Version introduction, the introduction on the official website is as follows:

1

On Linux, the runtime now uses MADV_FREE to release unused memory. This is more efficient but may result in higher reported RSS. The kernel will reclaim the unused data when it is needed. To revert to the Go 1.11 behavior (MADV_DONTNEED), set the environment variable GODEBUG=madvdontneed=1.
Copy the code

With MADV_FREE, program memory will not be reclaimed immediately, i.e

The RSS value

It does not drop immediately. Only when the OS is short of memory will the Go program’s memory be reclaimed and returned to the OS.

Go 1.11 and previous versions used MADV_DONTNEED by default, and the RSS value of the program dropped quickly. Therefore, if you need to reduce the program memory footprint quickly, you can set the environment variable GODEBUG= madvdontNeed =1.

Note: This function of Go 1.12~1.15 is limited to Linux platform; The MADV_FREE mode is used by default only when the kernel version is 4.5 or later. If not, the default MADV_DONTNEED will be used

Runtime /mem_linux.go

123456789101112 var advise uint32if debug.madvdontneed ! = 0 { advise = _MADV_DONTNEED} else { advise = atomic.Load(&adviseUnused)}if errno := madvise(v, n, int32(advise)); advise == _MADV_FREE && errno ! = 0 {// MADV_FREE was added in Linux 4.5. Fall back to MADV_DONTNEED if it is // not supported. atomic.Store(&adviseUnused, _MADV_DONTNEED) madvise(v, n, _MADV_DONTNEED)}Copy the code

Reference:

In Go 1.12, the parameter of the top command RES is abnormally high

Go process HeapReleased goes up, but RSS doesn’t Go down causing a memory leak? — It’s not a memory leak

An improvement in Go 1.12 regarding memory free-not a memory leak

Go 1.16 was changed back

in

Go to 1.16

, the problem was optimized again,

On Linux, Runtime now releases memory to the operating system quickly by default (using MADV_DONTNEED), rather than lazily releasing memory when the operating system is under memory stress (using MADV_FREE).

This means that process-level memory statistics such as RSS will more accurately reflect the amount of physical memory used by the Go process. Therefore, in Go1.16, it is no longer necessary to configure GODEBUG= madvDONTNeed =1 to improve memory monitoring behavior.

through

123456789 func parsedebugvars() { // defaults debug.cgocheck = 1 debug.invalidptr = 1 if GOOS == "linux" { debug.madvdontneed = 1 } ... }Copy the code

I just specified it back

debug.madvdontneed = 1

It was a detour for the Go Team

Reference & Worth reading:

List some of the changes in Go1.16 that may affect you

New Go1.16 feature: Detail the memory management changes you need to know

There are a few noteworthy changes in Go 1.16