Repository navigation
Add an optional benchmark workflow - #57
Conversation
|
Doing it in Python seems amusing. ;-) It's potentially worth keeping in mind that GHA could pull https://github.com/koreader/koreader-sync-server/pkgs/container/kosync which I think contains the necessary Lua equivalents. It could even query Redis with redis-lua. But the networking might be annoying. tl;dr Since you're using Claude extensively here see to what extent it thinks the suggestion is feasible. Not an objection to Python, mainly curiosity. |
|
I'm happy to do whatever language. Python was by my direction, as I wasn't sure if this was something y'all would even be interested in. I can do a Lua rewrite, if that's preferable. |
|
It's possible it'd be more awkward to do the same thing with Lua; it's just that I think it's the obvious first choice to try in a Lua repo. ;-) I'd say give it a go since it'll just take the LLM some five minutes to figure it out regardless; if it's too awkward we'll go with the Python. |
Builds a base ref and a head ref with the repo Dockerfile, runs both in containers, and drives the same v1 requests at each. Manual dispatch only. It reports into the job summary, gates nothing, and exits non-zero only when a build fails, a container never answers /healthcheck, or more than 1% of requests fail, never on a timing. Arms are interleaved across repetitions and every figure is a ratio against the base measured in the same repetition, because a shared runner drifts by more than most changes worth measuring. Redis commands per request are reported separately from latency and throughput: those counts are exact, and the wall clock on shared hardware is not. scripts/benchmark.sh builds and runs the two containers. scripts/benchmark.lua drives the load and writes the report, and runs inside the server container under the resty CLI the image already carries, so the HTTP port and redis are both on loopback and there is no container networking. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Swapped it over to Lua. The driver runs inside the container with It's a bit bigger than the Python, 571 lines against 423, mostly because the image has no HTTP client so it writes the requests itself. Worth noting the rewrite caught something the Python had wrong: nginx closing a keepalive connection after |
It probably doesn't matter too much, but it includes LuaSocket which definitely comes with one. Something like |
|
You're right that it's in there. It's blocking though, so under |
Adds
.github/workflows/benchmark.yaml,scripts/benchmark.shandscripts/benchmark.lua. The shell builds two refs with the repo Dockerfile, starts a container for each and runs the interleaved loop; the Lua seeds redis, drives the load, readsINFO commandstatsand writes the job summary.Advisory.
workflow_dispatchonly, so it never runs on a push or a pull request and cannot turn anything red. It exits non-zero only when a build fails, a container never answers/healthcheck, or more than 1% of requests fail, never on a timing.The driver runs inside the server container under
/opt/openresty/bin/resty, which the image already installs. HTTP and redis are then both on loopback, so there is no container networking to arrange and redis needs no exposed port. The driver is copied in at run time, so it also works against a ref that predates it.Method: arms interleaved across repetitions,
FLUSHDBand a seed write before every measurement, a discarded warmup,CONFIG RESETSTATimmediately before each measured window, and every figure a paired ratio against the base within the same repetition. Redis commands per request are reported separately from latency and throughput, because the first is exact and the second is not trustworthy on shared hardware.Run it from Actions, Benchmark, Run workflow. Locally:
./scripts/benchmark.sh --engine podman --base origin/master --head HEAD.Verified under podman on an M3 Pro,
d941a63against current master, 3 repetitions of 5 seconds at 2 connections:The per-command table attributes all of it to
select, which is #58. Base and head both on master gives the noise floor on that machine: paired p50 within 7.2% and rps within 5.8%.actionlintis clean;shellcheckreports only SC2329 on thetraphandler.The workflow has not run on a GitHub runner, so the timeout, the two builds against a cold cache, and whether the timing half is legible on two shared vCPUs are guesses. The command counts do not depend on any of that.
No new dependencies: everything the driver uses is in the image already.