Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2.8 KiB
R-803 — papra OOM under its 256M limit: birth measurement and proposed limit (2026-10-02, bench 9401 on demo-hp)
Bench: LXC 9401 r803-papra on demo-hp (debian-13 amd64, swap 0, nesting+keyctl, 60G rootfs on nvme-scratch,
12 GiB). Code: catalog-wt febf58c + the uncommitted gate scripts. Image ghcr.io/papra-hq/papra:26.6.2-rootless.
Driver: r803_birth.py (scratchpad). It deploys the template the way the volume gate does (same build_env, same scratch
paths, docker compose create then start), samples the container's cgroup v2 every 2 s from creation
(memory.stat anon/file, memory.current, memory.peak, memory.events oom/oom_kill/max, plus docker status/health/
restarts/OOMKilled), seeds once and reads back once with papra's own upgrade fixture (upgrade_fixtures_box.Papra through
upgrade_boxport.get), then idles 300 s. No Docker Hub login this time: the papra pull is from ghcr, and the canary base
image pulled anonymously.
1. From birth, no limit (birth-unlimited/)
The deploy block was removed in a separate run copy of the catalog (HostConfig.Memory=0).
- healthy at 71.5 s (the image pull is included in that time), 0 restarts,
oom_kill0 - peak anon 425,029,632 B = 405.3 MiB, sampled during first start/migration (4–28 s after start)
- peak
memory.current427 MiB; the cgroup's ownmemory.peak(anon + file, catches what 2-s sampling misses) 483 MiB - after healthy: anon ~356 MiB for ~2 min, then settles at ~254 MiB idle, which is already near the old 256M limit
- fixture:
papra: sign-up http=200→ seed OK;papra: sign-in as the seeded account http=200 ok=True→ read back true - volume after the run:
db/db.sqlite (581632 B)in the/app/app-datavolume
2. Proposed limit
405.3 MiB × 1.6 = 648 MiB → next catalog step 768M. 768M also covers the highest memory.peak seen (483 MiB) at 1.59×.
The bench template diff is in template.diff. It is NOT applied to the repo.
3. From birth at 768M (run-768M/)
- HostConfig.Memory=805306368 (768 MiB);
memory.max= 805306368 - healthy at 31.0 s, final status running/healthy, restarts 0, oom_kill 0, OOMKilled false
- fixture seed OK, read back true
- peak anon 297,943,040 B = 284.1 MiB,
memory.peak341 MiB, idle end anon 251 MiB. This run peaked lower than the unlimited run: the start-up peak varies between runs (memory.peak 341–483 MiB over two runs), so do not size from one run. - gate (
gate-papra-768M.txt, probe ingate-evidence/papra/probe.json), verbatim:papra CLEAN/1 clean · 0 broken · 0 undetermined (of 1 in scope)/volume-persistence gate OK/check-volume-persistence exit code = 0. Exercise172.18.0.2:1221/ -> 200;/app/app-dataholdsdb/db.sqlite.
Note: mem_request: "50M" in .felhom.yml was left unchanged (not in scope). Measured idle is ~255 MiB.