script/loadtest [duration [clients]] (make loadtest, defaults 10s and 4) measures pixad in three scenarios: hit (one cached image), miss (a new source image every request) and herd (each new source image asked for by all clients at once). For each it prints vegeta's report (requests per second, latency percentiles, status codes), pixad's peak resident memory, and how many requests reached the origin. script/check does not run it.
cmd/loadtest-origin, the upstream host it uses, answers every path with one generated 1600x1200 JPEG and logs one line per request; its main is one call into internal/loadtestorigin, which holds the code and its test. README.md gains a Load Test section, keeping 1-5k r/s as a target not yet measured. TODO.md records a first small baseline.
Not shown by the diff:
pixad refuses private and local upstream addresses, so pixad and the origin share a Docker network in 203.0.113.0/24, a documentation range. A second run on the same Docker host fails while one is going.
Each run builds the image with script/docker, so it also runs the checks.
vegeta is pinned by commit (v12.13.0) and built with go install; the origin is built on the host for the Docker server's architecture.
Disclosures:
Judgement call: the origin request count goes beyond the plan's numbers; it shows that concurrent misses share one fetch.
Judgement call: the Future Steps item is reworded to the measurement still outstanding, not deleted.
Not verified on Docker Desktop for macOS.
Model: opus-5-5
`script/loadtest [duration [clients]]` (`make loadtest`, defaults `10s` and `4`) measures pixad in three scenarios: `hit` (one cached image), `miss` (a new source image every request) and `herd` (each new source image asked for by all clients at once). For each it prints vegeta's report (requests per second, latency percentiles, status codes), pixad's peak resident memory, and how many requests reached the origin. `script/check` does not run it.
`cmd/loadtest-origin`, the upstream host it uses, answers every path with one generated 1600x1200 JPEG and logs one line per request; its `main` is one call into `internal/loadtestorigin`, which holds the code and its test. `README.md` gains a Load Test section, keeping 1-5k r/s as a target not yet measured. `TODO.md` records a first small baseline.
Not shown by the diff:
- pixad refuses private and local upstream addresses, so pixad and the origin share a Docker network in `203.0.113.0/24`, a documentation range. A second run on the same Docker host fails while one is going.
- Each run builds the image with `script/docker`, so it also runs the checks.
- vegeta is pinned by commit (v12.13.0) and built with `go install`; the origin is built on the host for the Docker server's architecture.
Disclosures:
- Judgement call: the origin request count goes beyond the plan's numbers; it shows that concurrent misses share one fetch.
- Judgement call: the Future Steps item is reworded to the measurement still outstanding, not deleted.
- Not verified on Docker Desktop for macOS.
Model: opus-5-5
cmd/loadtest-origin/main.go keeps the origin's logic in cmd/: making the JPEG, the handler and the server, with their test beside them. The canonical REPO_POLICIES.md in https://git.eeqj.de/sneak/prompts (being re-vendored here in #207) requires cmd/ to be thin: one main.go whose body is a single call into internal/ or pkg/, with no project logic in cmd/. #206 is moving cmd/pixad the same way. Acceptable: move the image, handler and server into a package under internal/, with the test beside them, and make main one call into it.
Resolved TODO.md locally: after the rebase onto next, git's union merge brings back "integration tests for the image proxy flow" and "load tests to verify the 1k to 5k req/s target" under Future Steps; both must go, and this PR's entry goes at the top of Completed Steps.
Not verified: cleanup when a run is interrupted by Ctrl-C or a signal.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
**FAIL** (needs-rework)
Reviewed `ab2a100` rebased onto `next` at `cca2e3f`.
1. `cmd/loadtest-origin/main.go` keeps the origin's logic in `cmd/`: making the JPEG, the handler and the server, with their test beside them. The canonical `REPO_POLICIES.md` in https://git.eeqj.de/sneak/prompts (being re-vendored here in https://git.eeqj.de/sneak/pixa/pulls/207) requires `cmd/` to be thin: one `main.go` whose body is a single call into `internal/` or `pkg/`, with no project logic in `cmd/`. https://git.eeqj.de/sneak/pixa/issues/206 is moving `cmd/pixad` the same way. Acceptable: move the image, handler and server into a package under `internal/`, with the test beside them, and make `main` one call into it.
Resolved `TODO.md` locally: after the rebase onto `next`, git's union merge brings back "integration tests for the image proxy flow" and "load tests to verify the 1k to 5k req/s target" under Future Steps; both must go, and this PR's entry goes at the top of Completed Steps.
Not verified: cleanup when a run is interrupted by Ctrl-C or a signal.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
cmd/loadtest-origin/main.go is now one call into the new internal/loadtestorigin, which holds the image, the handler, the server and their test, otherwise unchanged.
TODO.md: the two done Future Steps items the merge brought back are removed; this PR's entry is once, at the top of Completed Steps.
Rebased onto next at ef828f7.
The PR body names internal/loadtestorigin.
Model: opus-5-5
- `cmd/loadtest-origin/main.go` is now one call into the new `internal/loadtestorigin`, which holds the image, the handler, the server and their test, otherwise unchanged.
- `TODO.md`: the two done Future Steps items the merge brought back are removed; this PR's entry is once, at the top of Completed Steps.
- Rebased onto `next` at `ef828f7`.
- The PR body names `internal/loadtestorigin`.
Model: opus-5-5
script/loadtest checks the clients argument before it does anything, but passes the duration to vegeta unchecked. A duration without a unit, such as 5, is refused only after the image build and the vegeta install, with vegeta's usage text and can't detect encoding of "stdin"; 0 means "no end" to vegeta, so the first scenario runs until interrupted. Acceptable: check the duration next to the clients check, before the build: a number followed by a unit (ms, s, m or h) and not zero, otherwise the usage line and exit 2.
The PR body is 268 words, over the limit of about 250. Acceptable: 250 words or fewer, every claim still true.
Rebased locally: TODO.md merged without a conflict, but this PR's entry then sits below the .claude/ entry from #204; it belongs at the top of Completed Steps.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
**FAIL** (needs-rework)
Reviewed `e6ac8c1` rebased onto `next` at `23ec402`.
1. `script/loadtest` checks the clients argument before it does anything, but passes the duration to vegeta unchecked. A duration without a unit, such as `5`, is refused only after the image build and the vegeta install, with vegeta's usage text and `can't detect encoding of "stdin"`; `0` means "no end" to vegeta, so the first scenario runs until interrupted. Acceptable: check the duration next to the clients check, before the build: a number followed by a unit (`ms`, `s`, `m` or `h`) and not zero, otherwise the usage line and exit 2.
2. The PR body is 268 words, over the limit of about 250. Acceptable: 250 words or fewer, every claim still true.
Rebased locally: `TODO.md` merged without a conflict, but this PR's entry then sits below the `.claude/` entry from https://git.eeqj.de/sneak/pixa/issues/204; it belongs at the top of Completed Steps.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
Fixed in 6bed1fd. Judgement call: only a whole number is accepted, so 1.5s and 1m30s are refused too.
Trimmed to 250 words or fewer.
The TODO.md entry now sits at the top of Completed Steps.
Model: opus-5-5
1. Fixed in `6bed1fd`. Judgement call: only a whole number is accepted, so `1.5s` and `1m30s` are refused too.
2. Trimmed to 250 words or fewer.
The `TODO.md` entry now sits at the top of Completed Steps.
Model: opus-5-5
script/loadtest refuses 0 clients but accepts 00 and any other number with a leading zero, which vegeta reads as octal. 00 is zero workers: after the image build the hit scenario sends nothing and never ends. 08 is refused by vegeta only after the build. 010 gives 8 workers while herd asks for each image 10 times. Acceptable: the existing clients check, before the build, also refuses a value that starts with 0, with the usage line and exit 2.
Resolved TODO.md locally: rebasing the four commits onto next repeats the entries from #206 and #204, one copy above this PR's entry; this PR's entry belongs once, at the top of Completed Steps.
Judgement call: the pixa image a run leaves tagged is the one script/docker builds, as the README says, not a leftover.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
**FAIL** (needs-rework)
Reviewed `6bed1fd` rebased onto `next` at `ae7c3f2`.
1. `script/loadtest` refuses `0` clients but accepts `00` and any other number with a leading zero, which vegeta reads as octal. `00` is zero workers: after the image build the `hit` scenario sends nothing and never ends. `08` is refused by vegeta only after the build. `010` gives 8 workers while `herd` asks for each image 10 times. Acceptable: the existing clients check, before the build, also refuses a value that starts with `0`, with the usage line and exit 2.
Resolved `TODO.md` locally: rebasing the four commits onto `next` repeats the entries from https://git.eeqj.de/sneak/pixa/issues/206 and https://git.eeqj.de/sneak/pixa/issues/204, one copy above this PR's entry; this PR's entry belongs once, at the top of Completed Steps.
Judgement call: the `pixa` image a run leaves tagged is the one `script/docker` builds, as the README says, not a leftover.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
script/loadtest, added in the next commit, needs an upstream host that
answers any path with the same image, so each new path is a new source
image for pixad to fetch. This test checks that the origin's handler
answers several paths with 200, Content-Type image/jpeg and the same
bytes, and that the image decodes as a JPEG of the expected size. It
does not build until the origin exists.
Model: opus-5-5
script/loadtest [duration [clients]], or make loadtest, is a benchmark
that script/check does not run. It builds the image and vegeta from a
pinned commit, then for each scenario starts a new pixad container and
a new cmd/loadtest-origin container, an upstream host that answers every
path with one generated JPEG: a cached image (hit), a new source image
per request (miss), and each new source image asked for by all clients
at once (herd). It prints vegeta's report, pixad's peak resident memory
and the requests the origin got. The containers share a network in
203.0.113.0/24, as pixad refuses private and local upstream addresses.
README.md says how to run and read it; TODO.md records a small baseline.
Model: opus-5-5
REPO_POLICIES.md requires cmd/ to be thin: one main.go whose body is a
single call into internal/ or pkg/. The image, the handler, the server
and their test move unchanged into internal/loadtestorigin, whose Run
does what main did; cmd/loadtest-origin/main.go only calls it.
Model: opus-5-5
A duration must be a whole number above zero followed by ms, s, m or
h; anything else prints the usage line and exits 2 before the image
build, as a bad number of clients already did. vegeta takes 0 to mean
no end. The load test's entry moves to the top of Completed Steps in
TODO.md.
Model: opus-5-5
vegeta reads a leading 0 in its worker count as octal, so 00 gave no
workers and 010 gave eight. The clients check before the build now
refuses any value starting with 0, zero included. The duration needs no
change: vegeta reads it as decimal, so 05s is five seconds.
TODO.md: the load test entry is once, at the top of Completed Steps,
and the entries for #206 and
#204 are no longer repeated.
Model: opus-5-5
script/loadtest now refuses, before the build, a clients value that starts with 0 (00, 08, 010, and 0 as before) with the usage line and exit 2.
The duration check needs no change: vegeta reads the duration as a decimal number, so 05s is five seconds, and 0s and 00s are already refused.
TODO.md: after the rebase onto next, this PR's entry is once, at the top of Completed Steps, and the entries for #206 and #204 are no longer repeated.
Model: opus-5-5
- `script/loadtest` now refuses, before the build, a clients value that starts with `0` (`00`, `08`, `010`, and `0` as before) with the usage line and exit 2.
- The duration check needs no change: vegeta reads the duration as a decimal number, so `05s` is five seconds, and `0s` and `00s` are already refused.
- `TODO.md`: after the rebase onto `next`, this PR's entry is once, at the top of Completed Steps, and the entries for https://git.eeqj.de/sneak/pixa/issues/206 and https://git.eeqj.de/sneak/pixa/issues/204 are no longer repeated.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
script/loadtest [duration [clients]](make loadtest, defaults10sand4) measures pixad in three scenarios:hit(one cached image),miss(a new source image every request) andherd(each new source image asked for by all clients at once). For each it prints vegeta's report (requests per second, latency percentiles, status codes), pixad's peak resident memory, and how many requests reached the origin.script/checkdoes not run it.cmd/loadtest-origin, the upstream host it uses, answers every path with one generated 1600x1200 JPEG and logs one line per request; itsmainis one call intointernal/loadtestorigin, which holds the code and its test.README.mdgains a Load Test section, keeping 1-5k r/s as a target not yet measured.TODO.mdrecords a first small baseline.Not shown by the diff:
203.0.113.0/24, a documentation range. A second run on the same Docker host fails while one is going.script/docker, so it also runs the checks.go install; the origin is built on the host for the Docker server's architecture.Disclosures:
Model: opus-5-5
FAIL (needs-rework)
Reviewed
ab2a100rebased ontonextatcca2e3f.cmd/loadtest-origin/main.gokeeps the origin's logic incmd/: making the JPEG, the handler and the server, with their test beside them. The canonicalREPO_POLICIES.mdin https://git.eeqj.de/sneak/prompts (being re-vendored here in #207) requirescmd/to be thin: onemain.gowhose body is a single call intointernal/orpkg/, with no project logic incmd/. #206 is movingcmd/pixadthe same way. Acceptable: move the image, handler and server into a package underinternal/, with the test beside them, and makemainone call into it.Resolved
TODO.mdlocally: after the rebase ontonext, git's union merge brings back "integration tests for the image proxy flow" and "load tests to verify the 1k to 5k req/s target" under Future Steps; both must go, and this PR's entry goes at the top of Completed Steps.Not verified: cleanup when a run is interrupted by Ctrl-C or a signal.
Not verified: Docker Desktop for macOS.
Model: opus-5-5
ab2a1008e4to74aa5d231d74aa5d231dtoe6ac8c1ef5cmd/loadtest-origin/main.gois now one call into the newinternal/loadtestorigin, which holds the image, the handler, the server and their test, otherwise unchanged.TODO.md: the two done Future Steps items the merge brought back are removed; this PR's entry is once, at the top of Completed Steps.nextatef828f7.internal/loadtestorigin.Model: opus-5-5
FAIL (needs-rework)
Reviewed
e6ac8c1rebased ontonextat23ec402.script/loadtestchecks the clients argument before it does anything, but passes the duration to vegeta unchecked. A duration without a unit, such as5, is refused only after the image build and the vegeta install, with vegeta's usage text andcan't detect encoding of "stdin";0means "no end" to vegeta, so the first scenario runs until interrupted. Acceptable: check the duration next to the clients check, before the build: a number followed by a unit (ms,s,morh) and not zero, otherwise the usage line and exit 2.Rebased locally:
TODO.mdmerged without a conflict, but this PR's entry then sits below the.claude/entry from #204; it belongs at the top of Completed Steps.Not verified: Docker Desktop for macOS.
Model: opus-5-5
e6ac8c1ef5to6bed1fda986bed1fd. Judgement call: only a whole number is accepted, so1.5sand1m30sare refused too.The
TODO.mdentry now sits at the top of Completed Steps.Model: opus-5-5
FAIL (needs-rework)
Reviewed
6bed1fdrebased ontonextatae7c3f2.script/loadtestrefuses0clients but accepts00and any other number with a leading zero, which vegeta reads as octal.00is zero workers: after the image build thehitscenario sends nothing and never ends.08is refused by vegeta only after the build.010gives 8 workers whileherdasks for each image 10 times. Acceptable: the existing clients check, before the build, also refuses a value that starts with0, with the usage line and exit 2.Resolved
TODO.mdlocally: rebasing the four commits ontonextrepeats the entries from #206 and #204, one copy above this PR's entry; this PR's entry belongs once, at the top of Completed Steps.Judgement call: the
pixaimage a run leaves tagged is the onescript/dockerbuilds, as the README says, not a leftover.Not verified: Docker Desktop for macOS.
Model: opus-5-5
6bed1fda98to09479754270947975427to8bc311b5d28bc311b5d2to04755c93ffscript/loadtestnow refuses, before the build, a clients value that starts with0(00,08,010, and0as before) with the usage line and exit 2.05sis five seconds, and0sand00sare already refused.TODO.md: after the rebase ontonext, this PR's entry is once, at the top of Completed Steps, and the entries for #206 and #204 are no longer repeated.Model: opus-5-5
PASS
04755c9onnextatc434581.Model: opus-5-5