Skip to content

Commit

Permalink
runtime: add the disablethp GODEBUG setting
Browse files Browse the repository at this point in the history
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.

Fixes golang#64332.

Change-Id: I73b1894337f0f0b1a5a17b90da1221e118e0b145
Reviewed-on: https://go-review.googlesource.com/c/go/+/547475
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
mknyszek authored and ezz-no committed Feb 17, 2024
1 parent 5b65733 commit 82fb0af
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 0 deletions.
13 changes: 13 additions & 0 deletions doc/godebug.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@ when the connection supports neither TLS 1.3 nor Extended Master Secret
(implemented in Go 1.21). It can be reenabled with the [`tlsunsafeekm`
setting](/pkg/crypto/tls/#ConnectionState.ExportKeyingMaterial).

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

### Go 1.21

Go 1.21 made it a run-time error to call `panic` with a nil interface value,
Expand Down
7 changes: 7 additions & 0 deletions src/runtime/extern.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ It is a comma-separated list of name=val pairs setting these named variables:
cgocheck mode can be enabled using GOEXPERIMENT (which
requires a rebuild), see https://pkg.go.dev/internal/goexperiment for details.
disablethp: setting disablethp=1 on Linux disables transparent huge pages for the heap.
It has no effect on other platforms. disablethp is meant for compatibility with versions
of Go before 1.21, which stopped working around a Linux kernel default that can result
in significant memory overuse. See https://go.dev/issue/64332. This setting will be
removed in a future release, so operators should tweak their Linux configuration to suit
their needs before then. See https://go.dev/doc/gc-guide#Linux_transparent_huge_pages.
dontfreezetheworld: by default, the start of a fatal panic or throw
"freezes the world", preempting all threads to stop all running
goroutines, which makes it possible to traceback all goroutines, and
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/mem_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,12 @@ func sysMapOS(v unsafe.Pointer, n uintptr) {
print("runtime: mmap(", v, ", ", n, ") returned ", p, ", ", err, "\n")
throw("runtime: cannot map pages in arena address space")
}

// Disable huge pages if the GODEBUG for it is set.
//
// Note that there are a few sysHugePage calls that can override this, but
// they're all for GC metadata.
if debug.disablethp != 0 {
sysNoHugePageOS(v, n)
}
}
2 changes: 2 additions & 0 deletions src/runtime/runtime1.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ type dbgVar struct {
var debug struct {
cgocheck int32
clobberfree int32
disablethp int32
dontfreezetheworld int32
efence int32
gccheckmark int32
Expand Down Expand Up @@ -344,6 +345,7 @@ var dbgvars = []*dbgVar{
{name: "allocfreetrace", value: &debug.allocfreetrace},
{name: "clobberfree", value: &debug.clobberfree},
{name: "cgocheck", value: &debug.cgocheck},
{name: "disablethp", value: &debug.disablethp},
{name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
{name: "efence", value: &debug.efence},
{name: "gccheckmark", value: &debug.gccheckmark},
Expand Down

0 comments on commit 82fb0af

Please sign in to comment.