aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/godebug.md13
-rw-r--r--src/runtime/extern.go7
-rw-r--r--src/runtime/mem_linux.go8
-rw-r--r--src/runtime/runtime1.go2
4 files changed, 30 insertions, 0 deletions
diff --git a/doc/godebug.md b/doc/godebug.md
index d26555503e..4b71e4d469 100644
--- a/doc/godebug.md
+++ b/doc/godebug.md
@@ -134,6 +134,19 @@ The default is tlsmaxrsasize=8192, limiting RSA to 8192-bit keys. To avoid
denial of service attacks, this setting and default was backported to Go
1.19.13, Go 1.20.8, and Go 1.21.1.
+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,
diff --git a/src/runtime/extern.go b/src/runtime/extern.go
index 26dcf0bd52..de4a0ca2da 100644
--- a/src/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -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
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index c9823d3011..d63c38c209 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -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)
+ }
}
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index 92a7e021ee..7174c63af3 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -309,6 +309,7 @@ type dbgVar struct {
var debug struct {
cgocheck int32
clobberfree int32
+ disablethp int32
dontfreezetheworld int32
efence int32
gccheckmark int32
@@ -342,6 +343,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},