Skip to content

Commit 05e6d28

Browse files
committed
runtime: default to MADV_DONTNEED on Linux
In Go 1.12, we changed the runtime to use MADV_FREE when available on Linux (falling back to MADV_DONTNEED) in CL 135395 to address issue #23687. While MADV_FREE is somewhat faster than MADV_DONTNEED, it doesn't affect many of the statistics that MADV_DONTNEED does until the memory is actually reclaimed under OS memory pressure. This generally leads to poor user experience, like confusing stats in top and other monitoring tools; and bad integration with management systems that respond to memory usage. We've seen numerous issues about this user experience, including #41818, #39295, #37585, #33376, and #30904, many questions on Go mailing lists, and requests for mechanisms to change this behavior at run-time, such as #40870. There are also issues that may be a result of this, but root-causing it can be difficult, such as #41444 and #39174. And there's some evidence it may even be incompatible with Android's process management in #37569. This CL changes the default to prefer MADV_DONTNEED over MADV_FREE, to favor user-friendliness and minimal surprise over performance. I think it's become clear that Linux's implementation of MADV_FREE ultimately doesn't meet our needs. We've also made many improvements to the scavenger since Go 1.12. In particular, it is now far more prompt and it is self-paced, so it will simply trickle memory back to the system a little more slowly with this change. This can still be overridden by setting GODEBUG=madvdontneed=0. Fixes #42330 (meta-issue). Fixes #41818, #39295, #37585, #33376, #30904 (many of which were already closed as "working as intended"). Change-Id: Ib6aa7f2dc8419b32516cc5a5fc402faf576c92e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/267100 Trust: Austin Clements <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 33d9251 commit 05e6d28

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

src/runtime/extern.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ It is a comma-separated list of name=val pairs setting these named variables:
9191
# bytes memory allocated on the heap
9292
# allocs number of heap allocations
9393
94-
madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED
95-
instead of MADV_FREE on Linux when returning memory to the
96-
kernel. This is less efficient, but causes RSS numbers to drop
97-
more quickly.
94+
madvdontneed: setting madvdontneed=0 will use MADV_FREE
95+
instead of MADV_DONTNEED on Linux when returning memory to the
96+
kernel. This is more efficient, but means RSS numbers will
97+
drop only when the OS is under memory pressure.
9898
9999
memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate.
100100
When set to 0 memory profiling is disabled. Refer to the description of

src/runtime/runtime1.go

+11
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,17 @@ func parsedebugvars() {
352352
// defaults
353353
debug.cgocheck = 1
354354
debug.invalidptr = 1
355+
if GOOS == "linux" {
356+
// On Linux, MADV_FREE is faster than MADV_DONTNEED,
357+
// but doesn't affect many of the statistics that
358+
// MADV_DONTNEED does until the memory is actually
359+
// reclaimed. This generally leads to poor user
360+
// experience, like confusing stats in top and other
361+
// monitoring tools; and bad integration with
362+
// management systems that respond to memory usage.
363+
// Hence, default to MADV_DONTNEED.
364+
debug.madvdontneed = 1
365+
}
355366

356367
for p := gogetenv("GODEBUG"); p != ""; {
357368
field := ""

0 commit comments

Comments
 (0)