]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: default to MADV_DONTNEED on Linux
authorAustin Clements <austin@google.com>
Sun, 1 Nov 2020 22:48:42 +0000 (17:48 -0500)
committerAustin Clements <austin@google.com>
Mon, 2 Nov 2020 16:14:49 +0000 (16:14 +0000)
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 <austin@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/extern.go
src/runtime/runtime1.go

index b75507b8f85de8633436f314b0b54e6ea4c91492..dacdf4f38308da4de04b780c5993bf66209c75ff 100644 (file)
@@ -91,10 +91,10 @@ It is a comma-separated list of name=val pairs setting these named variables:
                # bytes     memory allocated on the heap
                # allocs    number of heap allocations
 
-       madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED
-       instead of MADV_FREE on Linux when returning memory to the
-       kernel. This is less efficient, but causes RSS numbers to drop
-       more quickly.
+       madvdontneed: setting madvdontneed=0 will use MADV_FREE
+       instead of MADV_DONTNEED on Linux when returning memory to the
+       kernel. This is more efficient, but means RSS numbers will
+       drop only when the OS is under memory pressure.
 
        memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate.
        When set to 0 memory profiling is disabled.  Refer to the description of
index 0f182ac58e6d41d45bbb81a957bf365366f73e6a..30b7044bffcf7e5f3ca17a2f622a2cdc21df6d5f 100644 (file)
@@ -352,6 +352,17 @@ func parsedebugvars() {
        // defaults
        debug.cgocheck = 1
        debug.invalidptr = 1
+       if GOOS == "linux" {
+               // On Linux, MADV_FREE is faster than MADV_DONTNEED,
+               // but doesn't affect many of the statistics that
+               // MADV_DONTNEED does until the memory is actually
+               // reclaimed. 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.
+               // Hence, default to MADV_DONTNEED.
+               debug.madvdontneed = 1
+       }
 
        for p := gogetenv("GODEBUG"); p != ""; {
                field := ""