Appendix H · Running the toolkit
What this holds
| Purpose | The make targets, how to check a figure against the repository, and what is in it |
| Source | Makefile, scripts/ci-check.sh, bench/results/ |
Nothing in this book needs to be run to be read. This page is for the point where you want to check a figure rather than trust it, or run a problem, or point the toolkit at your own numbers.
Installing it
The problems run in their chapters and need nothing. At a desk they need Python and nothing else. Building the book needs Node as well, for the parser that resolves its cross-references:
git clone https://github.com/snowch/sizing-and-tco.git
cd sizing-and-tco
python3 -m pip install -r requirements.txt -r requirements-dev.txt
npm install -g "mystmd@$(node -p "require('./package.json').devDependencies.mystmd")"What the commands do
make measure # re-take every constant that a codec decides
make models # evaluate and sample every model, and stamp what each one said
make figures # re-render every table and diagram from the stamped results
make check # everything CI runs
make book # live preview at localhost:3000Run make check before you believe anything. It is the same script CI runs, so the two cannot
drift, and it takes well under a minute.
Every model run in this book draws 100,000 samples from seed 20260916. Neither appears under the tables, because a constant repeated under ninety figures is not information, and a test fails if a run ever uses a different one, so that this sentence cannot quietly stop being true.
python3 -m pip, not a standalone tool install. python3 -m pytest has to work, and a pytest
installed by pipx or uv has its own environment and cannot import this repository’s code.
How to check a number in this book
Every figure on every page came out of a file under bench/results/. Pick one, say how well the
web service’s records compress, and follow it backwards:
python3 -c "import json; print(json.load(open('bench/results/records-compression.json'))['produced_by'])"
python3 -m bench.run_corpus --checkThe first prints the corpus, the codec and the implementation the figure belongs to. The second re-derives it from scratch on your machine and fails if it has moved. That is the whole contract: a number, what produced it, and a command that fails when the two have parted company.
The pages you are reading were built from this commit, which is where to point a checkout when a figure and the repository disagree:
Built from 0ec2b87, committed 2026-09-21.
Your laptop cannot take a timing on the reference machine, and the toolkit will not pretend it
can: verify-setup.py says so, and every figure that would need such a timing renders as a box
saying it has not been measured. ch03 is about why.
What is in the repository
| Constant | Target | Value | Standard error | Measured against |
|---|---|---|---|---|
logs-line-bytes | corpus | 32.4 bytes / line | ± 0.0044 | python zlib (DEFLATE level 6) |
metrics-sample-bytes | corpus | 9.37 bytes / sample | ± 0.0009 | this repository’s encoder, not any product’s |
records-compression | corpus | 3.58 | ± 0.0009 | python zlib (DEFLATE level 6) |
traces-span-bytes | corpus | 73.6 bytes / span | ± 0.0173 | python zlib (DEFLATE level 6) |
collector-throughput-per-core | — | not yet measured | — | — |
traces-spans-per-request | — | not yet measured | — | — |
Source — bench/results/, one row per stamped result
Every constant, including the ones nobody has measured. A row saying not yet measured is not a gap somebody forgot to fill; it is a figure this repository refuses to invent.
A model is a file. Here is what each one is made of:
| Node kind | Count | What it carries |
|---|---|---|
input | 37 | a value or a distribution, a provenance kind and a source |
derived | 51 | a formula, whose declared unit is checked against what it produces |
measured | 1 | a stamped result, a standard error, and the implementation it belongs to |
ceiling | 6 | a limit, a declared headroom, and a reason |
| classified as a sizing model — it has measured constants or ceilings in it, so sampling the inputs is not sufficient on its own |
Source — web_service-reference · every input on a slider
The last row says whether the build classifies the model as a cost model or a sizing one. It works
that out from the file, since a measured node or a ceiling makes it a sizing model, and
ch09 is where the reader’s own model crosses that line.
What this cannot tell you
Whether your machine gives the same answers as the one that produced these figures. The
corpus constants should agree, because a codec is deterministic. But a different Python, a
different compression library, or a processor that takes a different instruction path can move a
figure in its last digits. make check allows a tolerance looser than that noise and tighter than
anything this book prints, so the noise passes and a real change does not. Where to put that
tolerance is a judgement, not a fact.
Whether the tools are the right versions. verify-setup.py checks that things are present,
not that they are the versions the pins name. A dependency resolved differently is the commonest
reason a fresh checkout disagrees with CI, and the honest fix is to read requirements.txt rather
than to trust a tick.
Anything about the models themselves. Every check on this page is about whether the machinery runs. A model can pass every one of them and still be a bad description of your system. The chapters are about that.