footprint

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package footprint bounds and measures the control plane's idle cost: a default memory limit, a registry of background loops, and process stats.

Index

Constants

View Source
const (
	EnvTolRSSPct     = "IDLE_TOL_RSS_PCT"
	EnvTolGoroutines = "IDLE_TOL_GOROUTINES"
	EnvTolFDs        = "IDLE_TOL_FDS"
	EnvTolCPUPoints  = "IDLE_TOL_CPU_POINTS"
	EnvCPUWindowSecs = "APP_FOOTPRINT_CPU_WINDOW_SECONDS"
)

Environment variables shared with scripts/idle-footprint, which has no defaults on purpose.

View Source
const (
	StatusWithin       = "within_tolerance"
	StatusOver         = "over_tolerance"
	StatusNoBaseline   = "no_baseline"
	StatusToleranceOff = "tolerance_unset"
)

Assessment statuses.

View Source
const (
	EnvMemLimit        = "GOMEMLIMIT"
	EnvMemLimitPercent = "APP_GOMEMLIMIT_PERCENT"
	DefaultPercent     = 80
)

Env vars read by ApplyMemoryLimit.

View Source
const (
	EnvGCPercent      = "APP_GC_PERCENT"
	EnvTrimInterval   = "APP_MEM_TRIM_INTERVAL"
	EnvTrimMinIdleMB  = "APP_MEM_TRIM_MIN_IDLE_MB"
	EnvTrimBootDelay  = "APP_MEM_TRIM_BOOT_DELAY"
	DefaultTrimBoot   = 12 * time.Second
	DefaultGCPercent  = 50
	DefaultTrimEvery  = 2 * time.Minute
	DefaultTrimIdleMB = 24
)

Env vars read by ApplyGCPercent and RunTrim.

View Source
const DefaultSettingsPoll = 30 * time.Second

DefaultSettingsPoll is how often RunTrim re-reads the live settings; the trim itself still runs on its own interval.

Variables

This section is empty.

Functions

func ApplyGCPercent

func ApplyGCPercent(getenv func(string) string) int

ApplyGCPercent returns the percent it set, or 0 when GOGC already decides. It lowers the GC target below Go's 100 default unless GOGC or APP_GC_PERCENT is set; the live heap is small, so the extra GC cost is negligible.

func Attribute

func Attribute(name string) func()

Attribute counts the calling goroutine under name until the returned func runs.

func BootTotal

func BootTotal() time.Duration

BootTotal is the summed time of every recorded step.

func CPUWindowFromEnv

func CPUWindowFromEnv(get func(string) string) time.Duration

CPUWindowFromEnv returns the CPU averaging window, matching the baseline run's 60 seconds when unset.

func Every

func Every(ctx context.Context, name string, interval time.Duration, logger *slog.Logger, tick func(context.Context) error) error

Every runs tick on interval until ctx ends. The first tick is delayed by a random jitter of up to a tenth of the interval so loops do not wake together, and each tick is recorded.

func LimitFor

func LimitFor(total int64, percent int) int64

LimitFor returns percent of total bytes, or 0 when the result would be too small to be safe.

func Percent

func Percent(getenv func(string) string) int

Percent reads APP_GOMEMLIMIT_PERCENT; 0 disables the default limit.

func RecordBootStage

func RecordBootStage(name string, d time.Duration)

RecordBootStage notes one finished startup step. Past the bound it only adds to the total.

func Run

func Run(ctx context.Context, name string, fn func(context.Context))

Run executes fn with a pprof "subsystem" label and the live count held.

func RunTrim

func RunTrim(ctx context.Context, logger *slog.Logger, getenv func(string) string, live *LiveSettings)

RunTrim returns heap the runtime is holding but not using to the OS. Boot allocates transient hundreds of MB (catalog parse, password hashing) and the scavenger gives it back slowly, so RSS stays high for no reason. With live set it also re-reads the GC target, memory limit and trim knobs on every poll, in the same loop.

func Stream

func Stream(ctx context.Context, name string) func()

Stream labels the calling goroutine and counts it under name until the returned func runs, for handlers that cannot hand their body to Run.

func TimeBootStage

func TimeBootStage(name string, fn func() error) error

TimeBootStage runs fn and records its duration, returning fn's error unchanged.

func WindowCPU

func WindowCPU(window time.Duration, now time.Time, cpuSeconds float64) (percent, covered float64)

WindowCPU is the average CPU percent over the last window, or since process start until a full window exists. Each call adds a sample, so a polling caller keeps the window populated.

Types

type Assessment

type Assessment struct {
	Status    string        `json:"status"`
	Detail    string        `json:"detail,omitempty"`
	Platform  string        `json:"platform"`
	Current   Reading       `json:"current"`
	Baseline  *BaselineRow  `json:"baseline,omitempty"`
	Tolerance *Tolerance    `json:"tolerance,omitempty"`
	Checks    []MetricCheck `json:"checks"`
	// BootStages and BootTotalMS are additive and filled by the API layer; unmeasured until a real host reports them.
	BootStages  []BootStage `json:"boot_stages,omitempty"`
	BootTotalMS float64     `json:"boot_total_ms,omitempty"`
}

Assessment is the live footprint judged against the committed idle baseline.

func Assess

func Assess(cur Reading, rows []BaselineRow, goos, goarch string, tol Tolerance, tolErr error) Assessment

Assess compares a reading with the baseline row for this platform. The baseline records a peak RSS, so live RSS is held to the peak limit.

type BaselineRow

type BaselineRow struct {
	OS            string  `json:"os"`
	Arch          string  `json:"arch"`
	Apps          int     `json:"apps"`
	AppMode       string  `json:"app_mode"`
	WindowSeconds int     `json:"window_seconds"`
	RSSMB         float64 `json:"rss_mb"`
	PeakRSSMB     float64 `json:"peak_rss_mb"`
	CPUPercent    float64 `json:"cpu_percent"`
	Goroutines    int     `json:"goroutines"`
	OpenFDs       int     `json:"open_fds"`
	Threads       int     `json:"threads"`
	Loops         int     `json:"loops"`
}

BaselineRow is one committed idle measurement from scripts/idle-footprint-baseline.json.

func Baseline

func Baseline() []BaselineRow

Baseline returns the committed idle measurements compiled into the binary.

func SelectBaseline

func SelectBaseline(rows []BaselineRow, goos, goarch string, apps int) (BaselineRow, bool)

SelectBaseline picks the stopped-app row for this platform closest to the live app count.

type BootStage

type BootStage struct {
	Name       string  `json:"name"`
	DurationMS float64 `json:"duration_ms"`
}

BootStage is how long one named startup step took.

func BootStages

func BootStages() []BootStage

BootStages returns a copy of the recorded steps in start order.

type LiveSettings

type LiveSettings struct {
	GCPercent       func(context.Context) int
	MemLimitPercent func(context.Context) int
	TrimInterval    func(context.Context) time.Duration
	TrimMinIdleMB   func(context.Context) int
}

LiveSettings reads the runtime settings that tune the Go runtime. Nil funcs are skipped. footprint cannot import the settings package, so the caller supplies the readers.

type Loop

type Loop struct {
	// contains filtered or unexported fields
}

Loop records the runs of one background loop.

func Track

func Track(name string, interval time.Duration) *Loop

Track returns the registry entry for name, creating it on first use.

func (*Loop) Active

func (l *Loop) Active() func()

Active marks the loop running and returns the func that marks it stopped.

func (*Loop) Observe

func (l *Loop) Observe(start time.Time, err error)

Observe records one finished run that began at start.

type LoopInfo

type LoopInfo struct {
	Name         string    `json:"name"`
	IntervalSecs float64   `json:"interval_seconds"`
	Runs         int64     `json:"runs"`
	Errors       int64     `json:"errors"`
	LastRunAt    time.Time `json:"last_run_at"`
	LastDuration float64   `json:"last_duration_ms"`
	BusyMS       float64   `json:"busy_ms_total"`
	CostPercent  float64   `json:"cost_percent"`
	Running      bool      `json:"running"`
	LastError    string    `json:"last_error,omitempty"`
	// contains filtered or unexported fields
}

LoopInfo is the observable state of one background loop.

func Loops

func Loops() []LoopInfo

Loops returns every registered loop, busiest first.

type MemoryLimit

type MemoryLimit struct {
	LimitBytes int64  `json:"limit_bytes"`
	Source     string `json:"source"`
	Percent    int    `json:"percent"`
}

MemoryLimit describes what ApplyMemoryLimit decided.

func ApplyMemoryLimit

func ApplyMemoryLimit(getenv func(string) string, logger *slog.Logger) MemoryLimit

ApplyMemoryLimit sets a soft Go memory limit from the container or host memory unless GOMEMLIMIT is already set.

func ApplyMemoryLimitPercent

func ApplyMemoryLimitPercent(pct int, logger *slog.Logger) MemoryLimit

ApplyMemoryLimitPercent sets the soft limit to pct of system memory, or lifts it when pct is 0 or the result is too small to be safe. The caller checks GOMEMLIMIT first.

func CurrentMemoryLimit

func CurrentMemoryLimit() MemoryLimit

CurrentMemoryLimit returns what the last ApplyMemoryLimit call decided.

type MetricCheck

type MetricCheck struct {
	Name     string  `json:"name"`
	Unit     string  `json:"unit"`
	Current  float64 `json:"current"`
	Baseline float64 `json:"baseline"`
	Limit    float64 `json:"limit"`
	OK       bool    `json:"ok"`
}

MetricCheck is one live value next to its baseline and the limit the tolerance allows.

type Proc

type Proc struct {
	RSSBytes   uint64  `json:"rss_bytes"`
	HeapBytes  uint64  `json:"heap_bytes"`
	Goroutines int     `json:"goroutines"`
	Threads    int     `json:"threads"`
	OpenFDs    int     `json:"open_fds"`
	CPUSeconds float64 `json:"cpu_seconds"`
	CPUPercent float64 `json:"cpu_percent"`
}

Proc is a point in time reading of the process footprint.

func ReadProc

func ReadProc() Proc

ReadProc samples the process. CPUPercent is relative to the previous call (or process start for the first).

type Reading

type Reading struct {
	RSSBytes         uint64  `json:"rss_bytes"`
	CPUPercent       float64 `json:"cpu_percent"`
	CPUWindowSeconds float64 `json:"cpu_window_seconds"`
	Goroutines       int     `json:"goroutines"`
	OpenFDs          int     `json:"open_fds"`
	Threads          int     `json:"threads"`
	Apps             int     `json:"apps"`
}

Reading is the live control plane footprint compared against a baseline.

func Snapshot

func Snapshot(window time.Duration, apps int) Reading

Snapshot reads the process and its window CPU in one call.

type SubsystemCount

type SubsystemCount struct {
	Name  string `json:"name"`
	Count int64  `json:"count"`
}

SubsystemCount is the number of live goroutines attributed to one subsystem.

func Subsystems

func Subsystems() []SubsystemCount

Subsystems lists non-zero counts, largest first.

type Tolerance

type Tolerance struct {
	RSSPercent float64 `json:"rss_percent"`
	Goroutines int     `json:"goroutines"`
	FDs        int     `json:"open_fds"`
	CPUPoints  float64 `json:"cpu_points"`
}

Tolerance is how far a reading may rise above its baseline row.

func ToleranceFromEnv

func ToleranceFromEnv(get func(string) string) (Tolerance, error)

ToleranceFromEnv fails when any variable is unset or invalid: a guard with silent limits is a guard nobody tuned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL