Skip to content

Commit cf65d74

Browse files
mknyszekgopherbot
authored andcommitted
[release-branch.go1.21] runtime: add the disablethp GODEBUG setting
Go 1.21.1 and Go 1.22 have ceased working around an issue with Linux kernel defaults for transparent huge pages that can result in excessive memory overheads. (https://bugzilla.kernel.org/show_bug.cgi?id=93111) Many Linux distributions disable huge pages altogether these days, so this problem isn't quite as far-reaching as it used to be. Also, the problem only affects Go programs with very particular memory usage patterns. That being said, because the runtime used to actively deal with this problem (but with some unpredictable behavior), it's preventing users that don't have a lot of control over their execution environment from upgrading to Go beyond Go 1.20. This change adds a GODEBUG to smooth over the transition. The GODEBUG setting disables transparent huge pages for all heap memory on Linux, which is much more predictable than restoring the old behavior. For #64332. Fixes #64561. Change-Id: I73b1894337f0f0b1a5a17b90da1221e118e0b145 Reviewed-on: https://go-review.googlesource.com/c/go/+/547475 Reviewed-by: Michael Pratt <[email protected]> Auto-Submit: Michael Knyszek <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit c915215) Reviewed-on: https://go-review.googlesource.com/c/go/+/547636 Reviewed-by: Mauri de Souza Meneguzzo <[email protected]> TryBot-Bypass: Michael Knyszek <[email protected]> Auto-Submit: Matthew Dempsky <[email protected]>
1 parent ad1ec60 commit cf65d74

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

doc/godebug.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ The default is tlsmaxrsasize=8192, limiting RSA to 8192-bit keys. To avoid
134134
denial of service attacks, this setting and default was backported to Go
135135
1.19.13, Go 1.20.8, and Go 1.21.1.
136136

137+
Go 1.22 changed how the runtime interacts with transparent huge pages on Linux.
138+
In particular, a common default Linux kernel configuration can result in
139+
significant memory overheads, and Go 1.22 no longer works around this default.
140+
To work around this issue without adjusting kernel settings, transparent huge
141+
pages can be disabled for Go memory with the
142+
[`disablethp` setting](/pkg/runtime#hdr-Environment_Variable).
143+
This behavior was backported to Go 1.21.1, but the setting is only available
144+
starting with Go 1.21.6.
145+
This setting may be removed in a future release, and users impacted by this issue
146+
should adjust their Linux configuration according to the recommendations in the
147+
[GC guide](/doc/gc-guide#Linux_transparent_huge_pages), or switch to a Linux
148+
distribution that disables transparent huge pages altogether.
149+
137150
### Go 1.21
138151

139152
Go 1.21 made it a run-time error to call `panic` with a nil interface value,

src/runtime/extern.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ It is a comma-separated list of name=val pairs setting these named variables:
5555
cgocheck mode can be enabled using GOEXPERIMENT (which
5656
requires a rebuild), see https://pkg.go.dev/internal/goexperiment for details.
5757
58+
disablethp: setting disablethp=1 on Linux disables transparent huge pages for the heap.
59+
It has no effect on other platforms. disablethp is meant for compatibility with versions
60+
of Go before 1.21, which stopped working around a Linux kernel default that can result
61+
in significant memory overuse. See https://go.dev/issue/64332. This setting will be
62+
removed in a future release, so operators should tweak their Linux configuration to suit
63+
their needs before then. See https://go.dev/doc/gc-guide#Linux_transparent_huge_pages.
64+
5865
dontfreezetheworld: by default, the start of a fatal panic or throw
5966
"freezes the world", preempting all threads to stop all running
6067
goroutines, which makes it possible to traceback all goroutines, and

src/runtime/mem_linux.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,12 @@ func sysMapOS(v unsafe.Pointer, n uintptr) {
170170
print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n")
171171
throw("runtime: cannot map pages in arena address space")
172172
}
173+
174+
// Disable huge pages if the GODEBUG for it is set.
175+
//
176+
// Note that there are a few sysHugePage calls that can override this, but
177+
// they're all for GC metadata.
178+
if debug.disablethp != 0 {
179+
sysNoHugePageOS(v, n)
180+
}
173181
}

src/runtime/runtime1.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ type dbgVar struct {
309309
var debug struct {
310310
cgocheck int32
311311
clobberfree int32
312+
disablethp int32
312313
dontfreezetheworld int32
313314
efence int32
314315
gccheckmark int32
@@ -342,6 +343,7 @@ var dbgvars = []*dbgVar{
342343
{name: "allocfreetrace", value: &debug.allocfreetrace},
343344
{name: "clobberfree", value: &debug.clobberfree},
344345
{name: "cgocheck", value: &debug.cgocheck},
346+
{name: "disablethp", value: &debug.disablethp},
345347
{name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
346348
{name: "efence", value: &debug.efence},
347349
{name: "gccheckmark", value: &debug.gccheckmark},

0 commit comments

Comments
 (0)