Documentation
¶
Overview ¶
Package peakmem reads the kernel-tracked peak resident memory of a finished task. Two entry points cover the two ways scitq runs a command:
Docker task: the container's cgroup carries a `memory.peak` file (cgroup v2, kernel 5.19+) or `memory.max_usage_in_bytes` (v1). ReadDockerPeakMB tries both, in order, and returns 0 on failure.
Bare task: /proc/<pid>/status carries a `VmHWM` field with the process's high-water resident-set size. ReadProcessPeakMB parses that and returns 0 on any read/parse error.
Both readers are best-effort by design: peak_mem_mb ends up in the task row as NULL when we can't read it, which the MCP surface treats as "not observed" rather than "zero used". There's no per-second sampling anywhere in this package — the kernel has been tracking the peak all along; we read the counter once, at task terminal.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ReadDockerPeakMB ¶
ReadDockerPeakMB reads the peak memory a docker container used, in MB (integer, rounded down). Tries the cgroup v2 file first, then the v1 fallback; both silently return 0 on any read error so a caller can always ship the returned value up without a nil check.
containerID is the full 64-char id, not the truncated "docker ps" display id. Callers typically get it from `docker inspect` or the output of `docker run --cidfile <path>`.
func ReadDockerPeakMBWithDiag ¶
ReadDockerPeakMBWithDiag is ReadDockerPeakMB plus a per-candidate diagnostic summary. Used by the executor to emit a worker_event when the read fails, so an operator can pinpoint the layout mismatch (missing path? path exists but reads 0? kernel too old for memory.peak?) without SSH-ing to the worker.
func ReadProcessPeakMB ¶
ReadProcessPeakMB parses /proc/<pid>/status for VmHWM (peak resident memory). Returns 0 on any read/parse failure, or if the process has already been reaped and its /proc entry is gone.
VmHWM is reported in kilobytes ("VmHWM: 12345 kB"); we convert to MB (integer, rounded down) so the value fits an int32 comfortably even for terabyte-class processes.
Types ¶
type Sampler ¶
type Sampler struct {
// contains filtered or unexported fields
}
Sampler tracks the peak memory of a running docker container by re-reading the cgroup counter on a fixed cadence for the container's lifetime. This exists because a one-shot read at cmd.Wait return is UNRELIABLE on cgroup v2 with the systemd driver: systemd tears down docker-<CID>.scope as soon as the container process exits, and the memory.peak file is gone before the caller gets to it, even though `docker inspect` still returns metadata (Docker keeps its own container record independent of the cgroup scope). By sampling while the container is alive, the last observed value is a tight approximation of the true peak: memory.peak is monotonic, so a stale reading is a lower bound rather than a wrong number.
Zero-cost when the container never starts (goroutine exits after the CID-lookup deadline). Best-effort throughout: an unreadable file or a torn-down scope leaves Peak() at 0, and the caller sends NULL up.
func NewDockerSampler ¶
NewDockerSampler starts a background goroutine that polls the peak memory of a docker container identified by containerName. The goroutine first waits for the container to be inspectable (up to startupDeadline) so callers can construct the sampler at the same time they run `docker run` without having to wait for the CID to become discoverable first. interval is how often to re-read the cgroup counter while the container is alive; 1 s is a fine default (memory.peak is monotonic, so a 1 s lag on the "final" reading is a tight bound on an hours-long workload).