Help us shape the future of Go! Take the 2026 Go Developer Survey

machine

package
v0.155.6 Latest Latest
Warning

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

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

Documentation

Overview

Package machine reads the numbers that decide whether the workstation survives the next hour: RAM and swap, memory pressure, the Claude Desktop cgroup, tmpfs and disk, build slots, kind clusters and the kernel's OOM kills. Linux only: /proc, cgroup v2 and the journal.

Index

Constants

View Source
const (
	Ollama   = "ollama"
	Lemonade = "lemonade"
)

The host's model servers, which load models into the iGPU's memory.

Variables

This section is empty.

Functions

func FindMemcapScope added in v0.14.0

func FindMemcapScope(unit string) string

FindMemcapScope returns the cgroup of the capped run's scope unit (as a run event names it, "memcap-….scope") in its slot's slice or in memcap.slice itself, or "" when it has ended.

func FindScope

func FindScope() string

FindScope returns the largest Claude Desktop scope, or "" when none runs.

func GTTUsedMiB added in v0.38.0

func GTTUsedMiB(gpus []GPU) int

GTTUsedMiB is the GTT all devices pin.

func ParseOllamaLoads added in v0.38.0

func ParseOllamaLoads(journal string) map[string]string

ParseOllamaLoads maps each model blob to the address of the client whose request loaded it last: the first model request logged after the load that started before it (gin logs a request when it ends, with its latency). A blob whose last load's request is still running maps to "": an earlier load's client is not its.

func ParseOomd added in v0.45.2

func ParseOomd(journal string) []string

ParseOomd keeps the lines of systemd-oomd's journal where it killed a cgroup: the event that takes every session down at once.

func ReadCPUPSISome10 added in v0.38.1

func ReadCPUPSISome10() (float64, error)

ReadCPUPSISome10 returns CPU pressure "some avg10" in percent: the share of the last ten seconds in which at least one runnable task waited for a CPU.

func ReadForks added in v0.42.0

func ReadForks() (uint64, error)

ReadForks returns the processes forked since boot: the "processes" line of /proc/stat.

func ReadLoad

func ReadLoad() ([3]float64, error)

ReadLoad returns the 1, 5 and 15 minute load averages.

func ReadPSIFull60

func ReadPSIFull60() (float64, error)

ReadPSIFull60 returns memory pressure "full avg60" in percent: the share of the last minute in which every task stalled on memory.

func UnloadLemonade added in v0.45.0

func UnloadLemonade(ctx context.Context, url, model string) error

UnloadLemonade asks the Lemonade Server at url to drop model from memory now (POST /api/v1/unload); its weights stay on disk.

func UnloadOllama added in v0.40.0

func UnloadOllama(ctx context.Context, url, model string) error

UnloadOllama asks the ollama at url to drop model from memory now; its weights stay on disk and the next request loads it again.

func Zone added in v0.27.0

func Zone() (*time.Location, error)

Zone is the machine's time zone as timedatectl sets it, read now: a long-running process's time.Local stays the zone it started in.

Types

type BuildCPU added in v0.107.0

type BuildCPU struct {
	// Quota is the slice's cpu.max as a systemd CPUQuota ("1200%" is
	// twelve cores), "max" for none.
	Quota string `json:"quota"`
	// Weight is the slice's cpu.weight, against the desktop's slices (100
	// each).
	Weight int64 `json:"weight"`
	// UsePct is the CPU the slice used over the sample in percent of one
	// core, comparable to Quota.
	UsePct float64 `json:"usePct"`
	// Throttled is how many quota periods of the sample the slice ran
	// into its quota in.
	Throttled int64 `json:"throttled"`
}

BuildCPU is memcap.slice's CPU: the budget every capped run shares and its use over a sample.

func ReadBuildCPU added in v0.107.0

func ReadBuildCPU(sample time.Duration) *BuildCPU

ReadBuildCPU reads memcap.slice's CPU over a sample of the given length, or nil while the slice has no cgroup (no run since the user manager started).

type Cluster

type Cluster struct {
	Name   string `json:"name"`
	Nodes  int    `json:"nodes"`
	MemMiB int    `json:"memMiB"`
	// Containers are the node containers' full ids.
	Containers []string `json:"containers"`
	// RunningFor is docker's age of its oldest node ("2 hours ago").
	RunningFor string `json:"runningFor"`
}

Cluster is a running kind cluster.

func KindClusters

func KindClusters(ctx context.Context) ([]Cluster, error)

KindClusters lists the kind clusters from the node containers docker runs.

type Disk

type Disk struct {
	Path    string `json:"path"`
	UsedMiB int    `json:"usedMiB"`
	FreeMiB int    `json:"freeMiB"`
	// TotalMiB is the filesystem's size.
	TotalMiB int `json:"totalMiB"`
}

Disk is a filesystem's usage in MiB.

func ReadDisk

func ReadDisk(path string) (Disk, error)

ReadDisk returns the usage of the filesystem path lives on; free is what an unprivileged process can still write.

type GPU added in v0.38.0

type GPU struct {
	Device      string `json:"device"`
	GTTUsedMiB  int    `json:"gttUsedMiB"`
	GTTTotalMiB int    `json:"gttTotalMiB"`
	VRAMUsedMiB int    `json:"vramUsedMiB"`
	VRAMTotMiB  int    `json:"vramTotalMiB"`
}

GPU is an amdgpu device's memory in MiB. On an APU, GTT is system RAM the driver pins for the GPU: no cgroup counts it, but it is gone from MemAvailable all the same.

func ReadGPUs added in v0.38.0

func ReadGPUs() []GPU

ReadGPUs returns every amdgpu device's GTT and VRAM, none on a machine without one.

type HostModel added in v0.45.0

type HostModel struct {
	// Server is the model server holding it: Ollama or Lemonade.
	Server  string `json:"server"`
	Name    string `json:"name"`
	SizeMiB int    `json:"sizeMiB"`
	// GPUMiB is the part on the GPU: on an APU, GTT.
	GPUMiB    int       `json:"gpuMiB,omitempty"`
	ExpiresAt time.Time `json:"expiresAt,omitzero"`
	// Client is who sent the request that loaded it, as the server's log
	// shows it or, while that request still runs, as the one client
	// connected to the server: an address, with the kind node's name when
	// one has it.
	Client string `json:"client,omitempty"`
}

HostModel is a model one of the host's model servers holds in memory.

func LemonadeModels added in v0.45.0

func LemonadeModels(ctx context.Context, url string) ([]HostModel, error)

LemonadeModels asks the Lemonade Server at url which models it holds (GET /api/v1/health) and how large each one's weights are (GET /api/v1/models, in GB). Lemonade logs no client address: a model's client is the one peer connected to url's port, and none when several are. An empty url means none is watched.

func OllamaModels added in v0.38.0

func OllamaModels(ctx context.Context, url, unit string, serviceLog func(ctx context.Context, unit, grep string) ([]byte, error)) ([]HostModel, error)

OllamaModels asks the ollama at url which models it holds (GET /api/ps) and finds each one's loading client in the log of unit (serviceLog). A load whose request still runs is not in the journal yet: its client is the one peer connected to url's port, and none when several are. An empty url means none is watched.

func (HostModel) Label added in v0.45.0

func (m HostModel) Label() string

Label is the model's name after its server's, as the watch prints it.

func (HostModel) Node added in v0.45.0

func (m HostModel) Node() string

Node is the kind node's name in Client, "" when the client is none.

func (HostModel) Unload added in v0.45.0

func (m HostModel) Unload(ctx context.Context, url string) error

Unload asks the model server holding m to drop it from memory now; its weights stay on disk and the next request loads it again. url is that server's API.

type Mem

type Mem struct {
	TotalMiB     int `json:"totalMiB"`
	AvailableMiB int `json:"availableMiB"`
	SwapTotalMiB int `json:"swapTotalMiB"`
	// SwapUsedMiB is SwapTotal − SwapFree: the swap slots in use, on disk
	// and in zswap alike.
	SwapUsedMiB int `json:"swapUsedMiB"`
	// ZswappedMiB is the swapped-out memory zswap holds compressed in RAM
	// (Zswapped), ZswapPoolMiB the RAM its pool takes for it (Zswap).
	ZswappedMiB  int `json:"zswappedMiB,omitempty"`
	ZswapPoolMiB int `json:"zswapPoolMiB,omitempty"`
	// ZswapWrittenBackMiB is zswap's writeback since boot: the pages zswap
	// moved from its pool to the swap device (zswpwb of /proc/vmstat), which
	// grow disk swap without new swapping; 0 on a kernel without the counter.
	ZswapWrittenBackMiB int `json:"zswapWrittenBackMiB,omitempty"`
	ShmemMiB            int `json:"shmemMiB"`
}

Mem is /proc/meminfo in MiB, with zswap's writeback from /proc/vmstat.

func ReadMem

func ReadMem() (Mem, error)

ReadMem parses /proc/meminfo and zswap's writeback from /proc/vmstat; an unreadable /proc/vmstat leaves the writeback 0.

func (Mem) DiskSwapMiB added in v0.73.0

func (m Mem) DiskSwapMiB() int

DiskSwapMiB is the swap in use that zswap does not hold: the pages written to the swap device, the share that costs a disk read to bring back.

func (Mem) SwapSplit added in v0.73.0

func (m Mem) SwapSplit() string

SwapSplit says the swap in use as disk plus zswap, the two adding up to SwapUsedMiB.

type OOMDSwap added in v0.73.0

type OOMDSwap struct {
	// LimitPercent is SwapUsedLimit in whole percent of SwapTotal.
	LimitPercent int `json:"limitPercent"`
	// Monitored are the swap-monitored cgroups' paths.
	Monitored []string `json:"monitored,omitempty"`
}

OOMDSwap is what systemd-oomd does about swap: its SwapUsedLimit and the cgroups it watches for it (ManagedOOMSwap=kill). Past the limit it kills the largest swap user among them, however much RAM is free; with none watched it never kills for swap.

func ParseOomctlDump added in v0.73.0

func ParseOomctlDump(dump string) (OOMDSwap, error)

ParseOomctlDump reads the "Swap Used Limit" and the paths under "Swap Monitored CGroups" of an `oomctl dump`.

func ReadOOMDSwap added in v0.73.0

func ReadOOMDSwap(ctx context.Context) (OOMDSwap, error)

ReadOOMDSwap asks systemd-oomd for its swap rule (`oomctl dump`); an error when oomd does not answer.

func (OOMDSwap) HeadroomMiB added in v0.73.0

func (o OOMDSwap) HeadroomMiB(m Mem) int

HeadroomMiB is the swap growth left before the trigger; negative once swap is past it. oomd counts every swap slot in use, zswap's included.

func (OOMDSwap) Line added in v0.73.0

func (o OOMDSwap) Line(m Mem) string

Line says oomd's swap rule against m: the trigger and its headroom when a cgroup is swap-monitored, otherwise that oomd does not watch swap.

func (OOMDSwap) Watched added in v0.73.0

func (o OOMDSwap) Watched() bool

Watched reports whether oomd would kill for swap at all.

type OOMKill

type OOMKill struct {
	At         time.Time `json:"at"`
	PID        int       `json:"pid"`
	Task       string    `json:"task"`
	AnonMiB    int       `json:"anonMiB"`
	Constraint string    `json:"constraint,omitempty"`
	// Memcg is the cgroup whose limit was hit: a memcap scope or slot
	// slice, a kind lab's pod, or the desktop scope.
	Memcg string `json:"memcg,omitempty"`
	// TaskMemcg is the killed task's cgroup: its run's scope when the cap
	// of the slot slice the run shares was hit.
	TaskMemcg string `json:"taskMemcg,omitempty"`
}

OOMKill is one process the kernel killed for memory.

func ParseOOM

func ParseOOM(journal string) []OOMKill

ParseOOM pairs the kernel's oom-kill and "Killed process" lines by pid.

func (OOMKill) RunMemcg added in v0.80.0

func (k OOMKill) RunMemcg() string

RunMemcg is the cgroup that names the killed run: the task's scope, whichever cap of the run's slot was hit.

type Scope

type Scope struct {
	Path       string `json:"path"`
	CurrentMiB int    `json:"currentMiB"`
	AnonMiB    int    `json:"anonMiB"`
	SwapMiB    int    `json:"swapMiB"`
	High       string `json:"high"`
	Max        string `json:"max"`
	SwapMax    string `json:"swapMax"`
	OOMKills   int64  `json:"oomKills"`
	HighEvents int64  `json:"highEvents"`
}

Scope is the Claude Desktop cgroup: every session's CLI and MCP servers live in it, and systemd-oomd kills it whole.

func ReadScope

func ReadScope(path string) *Scope

ReadScope reads the cgroup at path.

type Slot

type Slot struct {
	N      int    `json:"n"`
	Free   bool   `json:"free"`
	Holder string `json:"holder,omitempty"`
}

Slot is one of memcap's build slots.

func ReadSlots

func ReadSlots(dir string, n int) []Slot

ReadSlots probes memcap's slot locks without blocking.

type SlotSlice added in v0.145.4

type SlotSlice struct {
	// Scopes are the run scopes in the slice that still hold processes.
	Scopes []string
	// CurrentMiB is the slice's memory, every scope's together.
	CurrentMiB int
}

SlotSlice is a build slot's slice: the runs still in it and its memory.

func ReadSlotSlice added in v0.145.4

func ReadSlotSlice(slice string) *SlotSlice

ReadSlotSlice reads the slot slice (as a Cap names it, "memcap-slot1_….slice"), nil when it has no cgroup.

Jump to

Keyboard shortcuts

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