Expand description
Peak memory for stuffr bench, measured in untimed child processes.
After a row’s timed runs, the parent runs the row once more, once for
compression and once for decompression, each in a child: bench’s own
executable re-run as stuffr __bench-memory-child <job> (see
ChildJob::to_args). getrusage’s ru_maxrss is a per-process
high-water mark, which is why each measurement needs a fresh process,
and why one per file in --per-file mode (the row reports the largest).
What a child measures. Its 64 KiB read buffer, its 64 KiB output
buffer and its open files (the compress child’s output file included)
are made first; then it samples its peak resident set as the baseline (the
high-water so far, which is its current size, since nothing has run
yet), runs the codec to the end, and reports the peak minus that
baseline, saturating at 0. So the number is the codec’s resident working
memory plus a few small fixed buffers; memory reserved but never touched
does not count. The compress child streams the input from the files
(each read stops at the length snapshotted at load, as in the timed
runs), so an encoder that buffers its whole input (the pure-tier zstd
encoder) shows memory growing with the input: that is what using it
costs. The compress child writes its compressed output to a guarded
temp file the parent created and armed, stuffr-bench-<pid>-<n>; the
decompress child then reads that file through the same 64 KiB buffered
source the timed runs use. So the row is compressed once more, not
twice (ruling F8), and a compress child that fails leaves nothing for
the decompress side, which then shows - too.
Same conditions as the timed runs: level, --threads (through
governor_for) and --memory-limit. The backend is not sent: the
child is the same executable, so it has the same one.
The wire. The child prints one line on stdout, ok <bytes> or
err <text>, and exits 0 or 1 to match. Anything else (a crash, a
signal, no line) is a failed measurement. A failure never fails the row:
its cell is - and the text goes to Memory::error. A refusal by
--memory-limit (an Error::ResourceLimit) reads refused by --memory-limit: …, so it is told apart from a crash.
A debug build’s child refuses, as bench does, so this path is not
reachable from the CLI tests; Runner lets the parent’s logic be
tested with a fake, and child_main is tested in-process.
Structs§
- Child
Job - What one child runs. Compress:
filesconcatenated as one stream, written toout(discarded whenNone). Decompress: exactly one file, the compressed copy;outisNone. - Process
Runner - Runs each job as
<this executable> __bench-memory-child …, with stdin closed and stdout and stderr captured, keeping its pid inRUNNING_CHILDwhile it runs. The executable is resolved once, when the runner is made at the start of the run, and reused for every child.
Enums§
- Side
- Which half of the round trip a child measures.
Constants§
- CHILD_
ARG - The hidden first argument that makes the binary a memory child. Not a
clap subcommand:
mainchecks for it before clap parses, so it is in no help text and the examples page’s guard (which walks clap) never sees it. - MEASURES
- Whether this platform’s memory figures have been verified: macOS
(
ru_maxrss) and Linux (/proc/self/status). Elsewhere (the BSDs, and off unix) bench reports memory as not measured (ruling F9).
Statics§
- RUNNING_
CHILD - The pid of the memory child the parent is waiting for, 0 when none. Set once the child is spawned, cleared once it has been waited for; the signal cleanup reads it to kill the child before bench dies.
Traits§
- Runner
- Runs one child job and returns its reply. The real one spawns a
process (
ProcessRunner); tests inject a fake.
Functions§
- child_
entry - The hidden entry
maincalls first:Noneunlessargs[1]isCHILD_ARG; otherwise runs the child, prints its reply line and returns its exit code. A debug build refuses. - child_
main - The child: runs
joband returns its peak resident memory above the baseline (see the module doc), in bytes. - describe
- How a measurement failure reads in
mem_error: a refusal by--memory-limit(ResourceLimit, which is also what an allocation failure becomes) says so; everything else is its own message. - interpret
- A finished child: its reply when it gave a well-formed one and its exit
status agrees (0 for
ok, failure forerr); otherwise a failure namingstatusand the first line of its stderr, if any. - measure_
memory measure_memory_withwith real child processes (runner). Only whereMEASURES: elsewhere the caller reports memory as not measured.- measure_
memory_ with - One row’s memory under
plan: a compress child and a decompress child per stream (plan.mode: one stream over every file, or one per file), reporting each side’s largest peak. Per stream the parent creates an armed temp file, the compress child writes the compressed stream into it, and the decompress child reads it back; it is removed before the next stream begins. Strictly after the row’s timed runs. - parse_
reply - A child’s stdout line:
Some(Ok(n))forok <n>,Some(Err(text))forerr <text>(text not empty),Nonefor anything else.