Commit 38f7932c authored by cznic's avatar cznic
Browse files

collapse the A/B scaffolding into constants

MEMORY_MADV and MEMORY_HOT_MB existed so the decommit policy could be gauged
against a real workload without rebuilding. That happened: production
simulations put the policy at nearly no cost against plain retention while
returning the hoard, and the branch was asked to land in this shape. So the
policy becomes what 56fccba2 said it would if it survived - MADV_DONTNEED and a
4 MiB hot window as compile-time constants, no environment surface.

Anyone still A/B-ing with the env vars: pin b447515e, the last commit that has
them.

go test passes with and without -tags=memory.counters, go vet -unsafeptr=false
and staticcheck are clean, and all supported targets cross-build.

Co-Authored-By: default avatarClaude Fable 5 <noreply@anthropic.com>
parent b447515e
Loading
Loading
Loading
Loading
+8 −29
Original line number Diff line number Diff line
@@ -7,47 +7,26 @@
package memory // import "modernc.org/memory"

import (
	"os"
	"strconv"
	"unsafe"

	"golang.org/x/sys/unix"
)

// EXPERIMENT SCAFFOLDING. The two environment variables exist only so this can
// be A/B'd against a real workload without rebuilding. Neither is a proposed
// API: if the policy lands, both collapse into constants.
//
//	MEMORY_MADV=dontneed|free|none	default dontneed
//	MEMORY_HOT_MB=<n>		default 4
var (
const (
	// madviseAdvice is the advice passed for a region falling out of the hot
	// window, or -1 to leave retained regions committed.
	// window.
	//
	// MADV_DONTNEED rather than MADV_FREE: MADV_FREE reclaims lazily, so the
	// resident set does not actually drop until the machine is under pressure
	// - measured, a 2 GiB pool still read as 2 GiB of RSS. That is the same
	// reason the Go runtime defaults to MADV_DONTNEED.
	madviseAdvice = func() int {
		switch os.Getenv("MEMORY_MADV") {
		case "free":
			return unix.MADV_FREE
		case "none":
			return -1
		default:
			return unix.MADV_DONTNEED
		}
	}()
	madviseAdvice = unix.MADV_DONTNEED

	// hotBytes is how much of the retained pool stays committed per size class.
	hotBytes = func() int {
		if s := os.Getenv("MEMORY_HOT_MB"); s != "" {
			if n, err := strconv.Atoi(s); err == nil {
				return n << 20
			}
		}
		return 4 << 20
	}()
	// hotBytes is how much of the retained pool stays committed per size
	// class. 4 MiB costs nothing measurable against not decommitting at all
	// (speedtest1 and production simulations) while returning the hoard above
	// it.
	hotBytes = 4 << 20
)

// decommit asks the kernel to reclaim the physical pages backing the empty