memusage

package
v1.58.1 Latest Latest
Warning

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

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

README

memusage

memusage.Log(ctx) records kernel memory high-water marks through the context's clog logger. Call it when an operation finishes to capture peaks even when the operation completes between monitoring samples:

import "github.com/chainguard-dev/terraform-infra-common/pkg/memusage"

func run(ctx context.Context) error {
    defer memusage.Log(ctx)
    // Perform the operation.
    return nil
}

The memory usage log entry contains:

Field Meaning
process_peak_rss_bytes Linux /proc/self/status VmHWM, converted from KiB to bytes. Excludes child processes and unmapped scratch files.
process_peak_rss_error Error reading or parsing process accounting, or null on success.
container_peak_memory_bytes Cgroup v2 memory.peak, falling back to v1 memory.max_usage_in_bytes when v2 accounting is absent. Includes charged scratch files and child processes.
container_peak_memory_source Accounting file path relative to /, or empty if no supported controller was found.
container_peak_memory_error Error reading or verifying container accounting, or null on success.

Each file read is bounded. The reader verifies current-process membership and the controller mount root; nested or unverified layouts remain unknown instead of reporting a parent's peak. Missing, malformed, or unsupported accounting is logged as null with an error, never as zero. Non-Linux platforms may report neither value.

These counters describe the process and cgroup lifetimes, respectively, rather than one operation. Calls do not reset the counters. A hard kill or OOM can prevent a deferred log, so continue checking execution status and monitoring metrics.

Log and ReadContainer keep no shared state. All functions are safe for concurrent use.

memusage.ReadContainer() returns the container cgroup's current usage, limit, lifetime peak, and the memory.stat split of current usage (Anon, Shmem, File, InactiveFile) for callers that sample memory themselves. It uses the same bounded, verified reads: each value is a *uint64 with its own error, and a missing, malformed, or unlimited (max) value is nil with an error, never zero.

Heartbeat

memusage.Heartbeat(ctx) samples the container cgroup every second and logs a memory heartbeat entry while the working set is at or over half the limit: once a minute, and at once whenever the working set grows by 1/32 of the limit over its lowest sample since the last entry, so a climb that follows a drop still logs. Growth entries are capped at 16 a minute, the most steps a climb from half to the limit can take, so an instance logs at most 17 entries a minute even when its usage churns. A climb is logged in full unless churn earlier in the same minute spent the cap; then it waits for the next once-a-minute entry, which carries the peak. Below half it logs nothing. The working set is current usage minus inactive page cache, as the kubelet counts it, so a service that only fills the page cache stays quiet. When it cannot read the usage or the limit, it logs one memory heartbeat unavailable entry with the errors. Only the first call in a process samples; later calls return at once.

httpmetrics.SetupMetrics and httpmetrics.ServeMetrics start it, so most services get it without a code change.

Cloud Run SIGKILLs an instance that reaches its memory limit. When the memory is files in the in-memory /tmp or child processes, it logs no out-of-memory event, and these entries are the only record of what filled memory.

Field Meaning
cgroup_current_bytes, cgroup_limit_bytes, cgroup_peak_bytes Current, Limit, and Peak from ReadContainer.
cgroup_working_set_bytes cgroup_current_bytes minus cgroup_inactive_file_bytes; the value compared with the limit.
cgroup_anon_bytes Anonymous memory of every process in the container: the Go heap and child processes such as git.
cgroup_shmem_bytes Files in tmpfs mounts, such as Cloud Run's /tmp.
cgroup_file_bytes Page cache, including cgroup_shmem_bytes.
cgroup_inactive_file_bytes Page cache the kernel reclaims first under pressure.
cgroup_*_error Why the matching value is null, or null when it was read.
go_heap_alloc_bytes, go_sys_bytes, goroutines The Go runtime's own view, for comparison with cgroup_anon_bytes.

Documentation

Overview

Package memusage reads and logs Linux process and container memory accounting. Log and ReadContainer read accounting on each call and keep no shared state. Heartbeat samples in the background and logs while the container is at or over half its memory limit. All functions are safe for concurrent use.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Heartbeat added in v1.58.1

func Heartbeat(ctx context.Context)

Heartbeat logs the container's memory use while it is at or over half its limit, until ctx is done. Cloud Run SIGKILLs an instance that reaches its limit, and when the memory is tmpfs files or child processes it logs no out-of-memory event, so these lines are the record of what filled memory. Each line splits usage into anonymous memory (Go heap and child processes), tmpfs files, and page cache. Only the first call in a process samples; later calls return at once, so every entry point can start it.

func Log

func Log(ctx context.Context)

Log records Linux kernel memory high-water marks with the context logger. Missing or unsupported accounting is logged as null with an error, not zero. The process RSS excludes children and unmapped tmpfs; the cgroup peak includes all memory charged to the container, including child processes and scratch files. These are lifetime peaks, not per-call measurements. Log is safe for concurrent use.

Types

type Container added in v1.56.0

type Container struct {
	// Current is the memory charged to the container now: cgroup v2
	// memory.current or v1 memory.usage_in_bytes.
	Current    *uint64
	CurrentErr error

	// Limit is the memory limit: cgroup v2 memory.max or v1
	// memory.limit_in_bytes. A v2 limit of "max" is unknown.
	Limit    *uint64
	LimitErr error

	// Peak is the lifetime high-water mark: cgroup v2 memory.peak or v1
	// memory.max_usage_in_bytes. It only rises, so it shows how close the
	// container came to its limit even between samples.
	Peak    *uint64
	PeakErr error

	// Anon, Shmem, and File split Current by kind, from memory.stat.
	// Anon is anonymous memory of every process in the container, the Go heap
	// and child processes alike (v2 anon, v1 total_rss). Shmem is files in
	// tmpfs mounts such as Cloud Run's in-memory /tmp (v2 shmem, v1
	// total_shmem). File is the page cache, and it includes Shmem (v2 file, v1
	// total_cache). On v1, the total_ keys include child cgroups, as
	// memory.usage_in_bytes does.
	Anon     *uint64
	AnonErr  error
	Shmem    *uint64
	ShmemErr error
	File     *uint64
	FileErr  error

	// InactiveFile is the page cache the kernel reclaims first under
	// pressure (v2 inactive_file, v1 total_inactive_file).
	InactiveFile    *uint64
	InactiveFileErr error
}

Container is a snapshot of the container cgroup's memory accounting, read from the controller mounted at the current process's root. A nil value is unknown, and its error says why; it is never reported as zero.

func ReadContainer added in v1.56.0

func ReadContainer() Container

ReadContainer reads the container cgroup's current usage, limit, lifetime peak, and the memory.stat breakdown of current usage. Each read is bounded and verified as Log's peak read is.

Jump to

Keyboard shortcuts

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