memory

package
v0.2.8 Latest Latest
Warning

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

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

Documentation

Overview

Package memory is the G2 idle-connection memory harness: the arithmetic half of equivalence-spec §3.6, with the three commands beside it supplying the server under test, the synthetic session driver, and the report.

What this measures

mem_per_session = ( M(N) − M(0) ) / N

where M(x) is the median of 60 samples taken at 1 Hz over the last 60 s of a five-minute steady-state window, and M(x) is the serving container's cgroup v2 memory.current minus memory.stat's file, read from OUTSIDE the process. equivalence-spec §3.6 is the normative text and this package does not restate it; what lives here is the part that must be executable and therefore testable — median over an even-length sample set, the subtraction, the division, and the refusal to produce a figure from a window that is not the window §3.6 specified.

The sampling itself is measure.sh, on the host, because the numbers are files under /sys/fs/cgroup that the measured container must not be the one reading. Bash reads them; this package turns the CSV into the figure, so the only arithmetic in the shell is a loop counter.

Why this is a SEPARATE module

Same reason as test/routers, examples/counter and examples/chat: a requirement in gotth-live/go.mod enters the build list of everybody who requires gotth-live, because Go resolves requirements at module granularity. The server under test wires the OpenTelemetry metric and trace SDKs — equivalence-spec §5.6 puts default-on observability inside the headline configuration, so the measured binary has to have a real provider rather than a nil one — and the SDKs are needed by nothing else in this repository. A benchmark's dependencies must not be a consumer's.

It also leaves internal/arch's two-exported-package cap alone, which lists every package under the module path: a package here would be counted as a third, and widening that assertion to let a benchmark through would weaken the thing it was written to catch.

Where this module DOES what test/routers refuses to do

test/routers is lexically under gotth-live/ and could therefore import gotth-live/internal/..., and deliberately does not: its subject is what a consumer can do from outside, so proving it with the library's own private codec would prove it with a tool no reader can pick up.

cmd/memdrv does import the internal protobuf types, and the difference is which side of the wire it stands on. The driver is not a consumer of the library; it stands in for the CLIENT RUNTIME, which is part of the library and is written in JavaScript. §3.6 requires the driver to speak "the actual protocol — real handshake, real events", and a second, hand-rolled encoder of gotthlive.v1.Frame would be a copy of the wire format that could drift from the schema while still passing every test in this module. Reading the generated types is what makes "real handshake" checkable rather than asserted.

cmd/memsrv, by contrast, uses only the exported live API, because it stands in for an application and the per-session cost being measured is the one an application pays.

Index

Constants

View Source
const (
	SpecSamples  = 60
	SpecPeriodMS = 1000
)

SpecSamples and SpecPeriodMS are equivalence-spec §3.6's sampling window, spelled out so that a window which is not that window is a failure rather than a footnote: "the median of 60 samples taken at 1 Hz over the last 60 s of a 5-minute steady-state window".

They are constants and not options. A harness that could be asked for 20 samples would eventually be asked for 20 samples, and the number in the report would still be called a §3.6 figure.

View Source
const InstabilitySpread = 0.20

InstabilitySpread is equivalence-spec §6's instability rule, applied to this dimension by analogy: "if the spread of per-run p50s exceeds 20 % of the pooled p50, the cell is marked unstable, the whole cell is re-collected (not selectively), and the unstable set is still published."

§6 states the rule for latency percentiles. Nothing in §6 states it for D3, and this constant does not invent an amendment: it applies the same threshold to the per-run mem_per_session figures and reports the verdict as a computed flag, so that a memory cell whose runs disagree is visible in the data instead of being averaged into a clean-looking number. A cell marked unstable here is published, exactly as §6 requires of the cells it does cover.

View Source
const PeriodToleranceMS = 150

PeriodToleranceMS is how far a sample's spacing may drift from 1 Hz before the window is rejected.

It exists because the sampler is a shell loop on a contended host, not a real-time system: a 1 Hz loop that sleeps for the remainder of each second lands within a few milliseconds when the host is quiet and can land tens of milliseconds late when it is not. 150 ms is wide enough that ordinary scheduling jitter does not throw away a five-minute window, and narrow enough that a sampler which missed a whole second — the failure that would silently shorten the window §3.6 fixes at 60 s — cannot pass.

Variables

This section is empty.

Functions

func CheckWindow

func CheckWindow(samples []Sample) error

CheckWindow reports whether a sample set is the window §3.6 specifies: 60 samples, 1 Hz, monotonic in time.

It is separate from Median so that the report says which of the two failed, and it is called before any figure is produced rather than alongside it.

func Median

func Median(samples []Sample) (float64, error)

Median returns M(x): the median of the samples' workload bytes.

The sample count §3.6 fixes is even, so "the median" needs a definition. It is the arithmetic mean of the two central order statistics — the ordinary convention, and the one that does not silently prefer the lower reading of a pair on a metric that only ever climbs. The return is float64 so that convention is not rounded away before the subtraction in PerSession; the report rounds once, at the end.

func PerSession

func PerSession(m0, mN float64, n int) (float64, error)

PerSession is §3.6's headline: ( M(N) − M(0) ) / N.

A negative result is returned rather than clamped. M(N) below M(0) means the two windows are not comparable — a different warm-up, a different container generation, or a host that moved underneath the run — and hiding it behind a zero would turn a broken run into a flattering one.

func SubLinear

func SubLinear(small, large Cell) (float64, bool, error)

SubLinear is RFC-0001 §6.3's check: per-session memory at N = 1000 must be within 15 % of N = 100. "If it grows, some structure is O(N) per session and that is a design defect, not a tuning problem."

It returns the relative difference and whether it is inside the bound. The difference is taken against the SMALLER concurrency, which is the reading that makes growth the failing direction.

Types

type Cell

type Cell struct {
	N    int   `json:"n"`
	Runs []Run `json:"runs"`

	// PooledPerSession is the median of the per-run figures. A median, not a
	// mean, for the same reason §3.6 medians its samples: one run that hit a
	// contended minute must not move the published number.
	PooledPerSession float64 `json:"pooled_mem_per_session_bytes"`
	MinPerSession    float64 `json:"min_mem_per_session_bytes"`
	MaxPerSession    float64 `json:"max_mem_per_session_bytes"`

	// Spread is (max − min) / pooled, and Unstable is that against
	// InstabilitySpread.
	Spread   float64 `json:"per_run_spread"`
	Unstable bool    `json:"unstable"`
}

Cell is every run of one (N, workload, configuration) combination.

func Summarize

func Summarize(runs []Run) (Cell, error)

Summarize pools a cell's runs.

It refuses a cell whose runs disagree about N, because the only way to pool figures from different concurrencies is to publish a number that is about neither.

type Run

type Run struct {
	ID string `json:"run_id"`
	N  int    `json:"n"`
	// Order records which window was collected first. It is carried because
	// the two windows are separate container lifecycles and a host that drifts
	// during a run would bias every run the same way if the order never
	// changed.
	Order string `json:"order"`

	M0 float64 `json:"m0_bytes"`
	MN float64 `json:"mn_bytes"`

	M0Samples int `json:"m0_samples"`
	MNSamples int `json:"mn_samples"`

	PerSession float64 `json:"mem_per_session_bytes"`
}

Run is one independent run of a cell: one M(0) window, one M(N) window, and the figure they produce.

type Sample

type Sample struct {
	// UnixMilli is when the sample was taken, on the host clock.
	UnixMilli int64
	// Current is memory.current.
	Current int64
	// File is memory.stat's file (page cache), the term §3.6 subtracts.
	File int64
	// Anon, Sock, Slab and Kernel are memory.stat's lines of the same names.
	Anon   int64
	Sock   int64
	Slab   int64
	Kernel int64
}

Sample is one reading of the measured container's cgroup v2 accounting, taken from the host.

Current and File are the two fields §3.6's definition of M(x) is written in; the rest are carried because they are free at sampling time and because an unexpected M(x) is answered by which line moved, not by re-running.

func ParseCSV

func ParseCSV(r io.Reader) ([]Sample, error)

ParseCSV reads a sample file written by measure.sh.

func (Sample) Workload

func (s Sample) Workload() int64

Workload is the sample's value of M(x)'s integrand: memory.current minus page cache, i.e. anonymous plus kernel memory attributable to the workload.

Directories

Path Synopsis
cmd
memdiag command
Command memdiag reports the G2 remediation diagnostic that diag.sh collects.
Command memdiag reports the G2 remediation diagnostic that diag.sh collects.
memdrv command
Command memdrv is equivalence-spec §3.6's synthetic session driver for gotth-live: it opens N real sessions against a memsrv, holds them IDLE, and keeps them alive for as long as the harness needs them.
Command memdrv is equivalence-spec §3.6's synthetic session driver for gotth-live: it opens N real sessions against a memsrv, holds them IDLE, and keeps them alive for as long as the harness needs them.
memsrv command
Command memsrv is the server under test for the G2 idle-connection memory baseline (RFC-0001 §6.1/§6.2, equivalence-spec §3.6).
Command memsrv is the server under test for the G2 idle-connection memory baseline (RFC-0001 §6.1/§6.2, equivalence-spec §3.6).
memstat command
Command memstat turns the sample files measure.sh collects into the figure equivalence-spec §3.6 defines, and refuses to produce one from a window that is not §3.6's window.
Command memstat turns the sample files measure.sh collects into the figure equivalence-spec §3.6 defines, and refuses to produce one from a window that is not §3.6's window.

Jump to

Keyboard shortcuts

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