Files
felhom.eu/documentation/audits/night-burndown-2026-10-06/r762/RESULT.md
T
2026-10-06 21:22:53 +02:00

3.3 KiB
Raw Blame History

R-762 second half — wger under gunicorn, measured (2026-10-06 night, bench 9401)

What was measured. wger 2.7 (wger/server:2.7, the catalog template on main d63ea35: DJANGO_DEBUG=False and the wger-files nginx), the template's limit 384M (deploy.resources.limits.memory: 384M; the file server 32M). Three runs, each on fresh volumes, on test bench VM 9401 (demo-hp): Django runserver (today's template), and gunicorn with 1 and 2 workers. No traefik: ports on the bench's loopback (wger 18000, the file server 18080). Script and compose: bench/run.sh, bench/compose.yml; raw outputs bench/out-*/.

How the worker count is set. The image's entrypoint runs gunicorn wger.wsgi:application --preload --bind 0.0.0.0:$PORT when WGER_USE_GUNICORN=True — no -w and no config file in the image, so gunicorn's own default applies: WEB_CONCURRENCY (unset = 1). Control from a different channel — the container's own log (bench/out-*/server-lines.txt): 1 × „Booting worker" for gunicorn1, 2 × for gunicorn2, „Starting development server" for runserver.

Mode Workers anon peak (MB) % of 384M oom_kill restarts ready after login page (10 × seq.) its CSS via wger-files 20 GETs, 10 parallel
runserver (today) — 201 52 % 0 0 81 s 200, avg 32 ms 200, 1 ms 200 ×20, avg 394 ms
gunicorn 1 165 43 % 0 0 75 s 200, avg 31 ms 200, 1 ms 200 ×20, avg 241 ms
gunicorn 2 157 41 % 0 0 72 s 200, avg 43 ms 200, 1 ms 200 ×20, avg 124 ms
  • anon peak: the highest anon in the container's memory.stat, sampled every 0.5 s from start to the end of the load (MB = MiB). memory.peak read 384 MiB in all three runs — the file cache fills the limit (collectstatic and the sqlite file); it is not the app's memory and caused no kill (memory note: memory.peak counts the page cache).
  • With --preload, the two workers share the app's pages with the master, so 2 workers did not cost more anon than 1 here (157 vs 165 MB; the difference is run-to-run noise, not a saving).
  • ready after: from compose up to the first 200 on the login page — dominated by bootstrap, collectstatic and migrate on a fresh volume, not by the server.

Not measured: a signed-in page. The scripted sign-in did not take (the form came back 200; the dashboard answered 302 to the login) and the brief said „if cheap". Nothing else was tried.

Pick the numbers support: gunicorn with 2 workers (WGER_USE_GUNICORN=True, WEB_CONCURRENCY=2): 41 % of the limit, no kill, and half the wait of 1 worker when ten requests arrive together. 1 worker also fits; runserver is the heaviest and is a development server.

Teardown. Bench 9401 was stopped when found; started 21:16, stopped again after the runs (pct status: stopped). The project's containers, volumes and network were removed by docker compose down -v on the project r762 only (0 left by name); /root/r762 deleted. The two images were already on the bench and stay. No prune of any kind. No Docker command ran on DooPlex. Host: nothing created (the copy files in /tmp were deleted). Hub: nothing. The image's default admin password appears in its own bootstrap log line; it is redacted in these files.