Files
homarr/scripts/benchmarks
Thomas Camlong dc46057544 docs(findings): definitive server-RAM A/B, and jemalloc rejected with evidence
Two things this settles.

First, the end-to-end number. Every Phase 2 result so far was an incremental A/B against
the build immediately before it, which cannot be summed. Rebuilt the merge-base
(06724cfeb) from a clean worktree and ran 2+2 alternated against HEAD, reporting cgroup
anonymous memory - the figure that counts against a container limit and cannot be
reclaimed:

  stage              before     after
  peak anon        376.6 ->   279.3 MiB  (-26%)
  boot idle        130.5 ->    62.4 MiB  (-52%)
  after sign-in    247.4 ->   142.9 MiB  (-42%)
  dashboard        293.4 ->   170.4 MiB  (-42%)
  4 tabs           366.5 ->   258.2 MiB  (-30%)
  after soak       323.7 ->   200.8 MiB  (-38%)
  peak node RSS    430.7 ->   336.2 MiB  (-22%)

No before/after range overlaps at any stage. Costs: CPU 23.5 -> 27.7s (+18%, solid,
non-overlapping). Median board load reads +30% but is NOT established - individual loads
were [506,383,1233] and [848,431,574] before against [780,808,515] and [621,579,1004]
after, heavily overlapping with no cold-then-warm pattern, so six samples per side cannot
separate a real regression from the variance.

compare-stress-runs.mjs now leads with anonMiB, which the harness recorded all along but
the report was ignoring in favour of memory.current - a figure that includes page cache
and swings 60+ MiB between runs of a byte-identical image.

Second, jemalloc. The largest attributed-but-unfixed item is ~38 MiB of V8 zone memory
that musl frees to its own pools and never returns to the kernel, so an allocator that
decays spans back to the OS looked like the answer. Tested on the byte-identical image
with only HOMARR_MALLOC differing, asserting the "Using jemalloc" log line:

  boot idle    62.4 ->  80.3 MiB  (+29%)
  after soak  215.5 -> 279.6 MiB  (+30%)
  4 tabs      259.9 -> 319.6 MiB  (+23%)
  CPU          28.0 ->  24.5 s    (-13%)

The hypothesis was backwards. jemalloc keeps more freed memory on purpose - thread caches
plus time-based dirty-page decay - and spends it on speed. 13% cheaper CPU, 18-30% more
resident memory. Reverted, and it closes off "swap the allocator" as a RAM direction:
musl is already the frugal choice here.
2026-08-10 18:25:00 +02:00
..