195 lines
16 KiB
Markdown
195 lines
16 KiB
Markdown
# Sizing check 2026-10-14 — do the estimator's numbers hold on a second machine, with apps together?
|
||
|
||
Box: demo-hp (AMD Ryzen Embedded V1756B, 4 cores / 8 threads, 29,994 MiB), guest 9201. Tools: the sizing bench
|
||
(`sizing-2026-10-13/tools/`: `bench.py`, `guest_sampler.sh`, `host_sampler.sh`, `actions.sh`) pointed at demo-hp — only the
|
||
box constants change. „Page says" figures are computed with `scripts/test_build_sizing_web.py`'s mirror of `sizing.js`
|
||
on `website/assets/sizing-data.json` (no JavaScript runtime on DooPlex). Deploys through the product; path fields take
|
||
their default (the enrolled drive). The box already runs 11 apps of its own (Home Assistant and Paperless among them);
|
||
they stay, and they are measured as they are.
|
||
|
||
## Predictions (written 00:20 UTC, before any deploy)
|
||
|
||
| Item | Page says | Prediction |
|
||
|---|---|---|
|
||
| „Just files and passwords" at rest (nextcloud + vaultwarden) | typical 314 + 44 MB; peak 525 + 99 MB | measured rest below the page's typical (N100 figures were taken idle) — 250–400 MB together |
|
||
| Immich during a 200-photo import, with the others busy too | peak 3,061 MB | 2.0–3.0 GB (the HP's faster CPU ends the ML jobs sooner, the peak is the same model loading) |
|
||
| Jellyfin forced transcode | peak 373 MB | 300–600 MB (`used` counts the file cache of the video) |
|
||
| Paperless 20 scans (consume folder) | peak 659 MB | 600–900 MB (OCR workers) |
|
||
| The set's real peak, all working at once, vs the page's sum of peaks (5,045 MB + platform 470) | 5,515 MB | **the real simultaneous peak is 60–80 % of the sum** — the page's „all at peak at once" is pessimistic, as it says |
|
||
| Platform (controller, traefik, cloudflared, filebrowser) | 470 MB | 350–500 MB |
|
||
|
||
## R1 — the numbers together (evidence `evidence/R1-set/`, summary `set-summary.json`)
|
||
|
||
Windows (UTC): rest A 00:18:02–00:48:02 (files + passwords only; the 00:30 db-dump falls inside); **together**
|
||
00:51:00–00:54:44 (Immich 200-photo import + its ML jobs, Jellyfin scan + forced 1080p transcode, Nextcloud 50 × 10 MiB
|
||
WebDAV upload — all three at once); Paperless 20 scans 01:01:40–01:08:33 (alone: the bench first put the scans in a
|
||
sub-folder, which Paperless does not read — moved at 01:01:40); rest B 01:08:40–01:29:30. `used` = memory.current −
|
||
inactive_file, per app summed over its containers (the sizing run's definition). No OOM kill anywhere (`memory.events`).
|
||
|
||
| App | Page typical | HP rest (median) | Diff | Page peak | HP peak (`used`) | Diff | HP `memory.peak` (incl. file cache) |
|
||
|---|---|---|---|---|---|---|---|
|
||
| immich | 1,356 | 1,557 | +15 % | 3,061 | 3,290 (during the import) | +7 % | 4,366 |
|
||
| jellyfin | 191 | 188 | −2 % | 373 | 448 (transcode) | +20 % | 497 |
|
||
| nextcloud | 314 | 229 | −27 % | 525 | 290 | **−45 %** | 808 |
|
||
| home-assistant (the box's own) | 318 | 352 | +11 % | 328 | 434 (after the 00:09 start) | **+32 %** | 441 |
|
||
| vaultwarden | 44 | 37 | −16 % | 99 | 40 | **−60 %** | 45 |
|
||
| paperless-ngx (the box's own) | 568 | 645 | +14 % | 659 | 755 (OCR) | +15 % | 903 |
|
||
| platform containers (controller, traefik, cloudflared, filebrowser) | 255 of the page's 470 (the other ~220 MB are the Docker daemons, not in any container — `build_sizing_web.py`) | 262 (rest B) – 347 (rest A) | +3 to +36 % | — | 386 | — | — |
|
||
|
||
| The set | Page (site rule) | Measured on the HP | Difference |
|
||
|---|---|---|---|
|
||
| „Just files and passwords": typical (sum) | 358 (+ platform 470 = 828) | 210 at rest (rest A); 265 after use | **−41 %** / −26 % |
|
||
| „Just files and passwords": peak | 624 (+ 470 = 1,094) | 326 (the 00:30 db-dump) | **−48 %** |
|
||
| „Family starter set": typical (sum) | 2,791 | 3,007 (rest B) | +8 % |
|
||
| „Family starter set": peak — the page's sum of peaks vs the **real** peak with three heavy apps busy at once | 5,045 (+ 470 = 5,515) | **4,900** at 00:52:35 (Paperless at rest then; with its OCR at the same time it would be ~5,100) | −3 % (≈ −0 % with Paperless) |
|
||
| platform | 470 (containers 255 + Docker daemons ~220) | containers 262–386; the daemons not sampled | the container part matches; the whole not measured |
|
||
| host's share (page: box − guest) | 32 GB box: 4,708 MB (box − guest 28,060 MiB) | not separable here: the HP host also runs Tester 1's 8 GB VM. Host used (MemTotal − MemAvailable) 13.4 GB in rest B, of which the guest's anon 3.8 GB | — |
|
||
|
||
**Prediction check:** „the real simultaneous peak is 60–80 % of the sum" — **wrong**. It was 97 %. Immich's import
|
||
peak alone is 65 % of the set's peak, and it coincides with Jellyfin's transcode and Nextcloud's upload as soon as a
|
||
family uses the box at the same time. The page's „all at peak at once" is not pessimistic for this set; it is about
|
||
right. The light apps (Nextcloud, Vaultwarden) are over-stated (corrected 07:30: an earlier draft compared the platform's containers with the whole 470 MB, which includes the Docker daemons); Immich, Jellyfin, Home Assistant are
|
||
under-stated.
|
||
|
||
### Second opinions for free — the box's own apps, sampled in the same run
|
||
|
||
Five of the 24 weakest page figures (source `telemetry` or `onboarding` **and** the sources disagree,
|
||
`sizing-2026-10-13/evidence/apps-table.json`) are apps this box already runs; R1 sampled them all night.
|
||
|
||
| App | Page source | Page typical | HP rest (median, rest B) | Diff | Page peak | HP peak (`used`, whole run, incl. the 00:09 start) | Diff |
|
||
|---|---|---|---|---|---|---|---|
|
||
| bookstack | telemetry | 159 | 148 | −7 % | 225 | 222 | −1 % |
|
||
| calibre-web | telemetry | 191 | 161 | −16 % | 413 | 242 | **−41 %** |
|
||
| kimai | telemetry | 163 | 155 | −5 % | 240 | 250 | +4 % |
|
||
| privatebin | telemetry | 40 | 38 | −5 % | 59 | 60 | +2 % |
|
||
| bentopdf | telemetry | 5 | 10 | +100 % (5 MB) | 10 | 15 | +50 % (5 MB) |
|
||
|
||
## R3 — are the page's three answers true on an 8 GB box?
|
||
|
||
**Where (decided by CC, 03:15):** scratch guest **9202**, not 9201. 9201 runs 11 apps of its own (2.6 GB at rest) that the
|
||
page's selection does not include; on a 4 GB guest they would decide the result. 9202 holds only the platform and a
|
||
Paperless — what the page models: the box plus the selected apps. Paperless is stopped for the first two selections and
|
||
started for the family set (it is part of it). **Memory:** `pct set 9202 --memory 4096` (the installer's
|
||
`autosize_guest_caps()` for an 8 GB box, = the page's `guestMib(8)`; was 25,898), swap 512 (Proxmox's default; the
|
||
installer sets none). **Restart:** the dashboard's restart answered 503 „agent not configured" — 9202 has no agent link
|
||
by design — so `pct reboot 9202`.
|
||
|
||
**Predictions (03:19, before any deploy):**
|
||
|
||
| Selection | Page says on 8 GB | Prediction |
|
||
|---|---|---|
|
||
| „Just files and passwords" | fits well | fits: no OOM kill, no swap, upload as fast as on 9201 |
|
||
| Immich alone | fits, but tight | works: no OOM kill; some swap during the ML jobs; the import 10–50 % slower than on 9201 |
|
||
| „Family starter set" | does not fit | real harm while all work at once: swap full, at least one OOM kill (most likely Immich's machine learning) or an app restart, the actions much slower |
|
||
|
||
### R3 results (evidence `evidence/R3-8gb/`, `evidence/R3b-family/`; counters from the guest cgroup `lxc/9202`)
|
||
|
||
The deploy itself warned from the second app on: „Az alkalmazások csúcsterhelése meghaladhatja a rendelkezésre álló
|
||
memóriát…" (Immich alone and every family app; not for files + passwords) — the product's own check agrees with the page.
|
||
„Hit the 4 GB limit" (`memory.events max`) happens in every selection — that is the file cache being reclaimed, not harm.
|
||
|
||
| Selection | Page says on 8 GB | OOM kills | Swap (512 MB) | The action | Every app answers? | Measured result |
|
||
|---|---|---|---|---|---|---|
|
||
| „Just files and passwords" | fits well | **0** | 19 MB | Nextcloud 50 × 10 MiB upload: 28 s, 50/50 | yes | **fits well — true** |
|
||
| Immich alone | fits, but tight | **14** — all in Immich's machine-learning container, at its own 1.5 GiB catalog limit (the same limit was reached on the big guest without a kill) | **full** (512 MB peak) | 200-photo import + jobs: 295 s (big guest: 221 s with two other apps busy), 200/200 | yes | **tight — true**; it works, slower, with ML workers killed and restarted |
|
||
| „Family starter set", run 1 (5 of 6: Nextcloud refused at install — its old data from run 1 was kept, 409 `kept_data_choice`) | does not fit | +2 | full; load average **151** on 4 cores | Immich upload 196/200 in 7.5 min (`immich-server` restarted); Paperless 20/20 | yes, after | harm |
|
||
| „Family starter set", run 2 (all 6, `R3b-family`) | does not fit | +4 (20 since the start) | full | Immich **116/200** (84 failed; `immich-server` restarted); Jellyfin transcode **1,322 s** (big guest: 87 s); Nextcloud 49/50 (one 503); Paperless **0/20** in 30 min | yes, after the work | **does not fit — true**: real harm |
|
||
|
||
**All three answers held on the 8 GB box.** The prediction for „Immich alone" (no OOM kill) was wrong: the ML container is
|
||
killed at its own limit when the guest is short of memory.
|
||
|
||
## R2 — the night backup next to the family set (evidence `evidence/R2-night/`, 01:32–02:51 UTC)
|
||
|
||
Tier 2 (01:30, 12 s) fell between the two samplings; Tier 1 (00:30, the database dumps) fell in R1's rest A. The
|
||
apps on 9201 at the time: the box's 11 + the bench's 4 (immich, jellyfin, nextcloud, vaultwarden).
|
||
|
||
| Window (UTC) | Controller container (Tier 3's restic runs inside it) | All apps in the guest (`used`) | Host used (MemTotal − MemAvailable) | Host CPU busy |
|
||
|---|---|---|---|---|
|
||
| quiet, 01:35–02:14 | 189 MB median, 209 max | 4,370 median | 13,323 median | 9 % median |
|
||
| Tier 3 restic → Storage Box, 02:15–02:18 (3 min 27 s, 11 apps, 120 snapshots) | 170 median, **308 max** (+~120 MB) | 3,901 median, 4,361 max | 12,943 median, 13,463 max | 30 % median, 69 % max |
|
||
| whole-guest vzdump on the HOST, 02:42–02:51 (cut by R3) | 84 median (the quiesce pauses apps) | 3,654 median | 13,480 median, **14,619 max** (+~1.1 GB, on the host) | 25 % median, 100 % max |
|
||
| Tier 1 db dumps, 00:30 (R1 rest A) | — | „files + passwords" peaked at 326 MB then (+~115 MB over its rest) | — | — |
|
||
|
||
**What the 1.5 headroom is for, measured:** inside the guest the backups add little — about 120 MB for Tier 3's restic and
|
||
about 115 MB for a database dump; apps do not grow during them. The big one, the whole-guest vzdump + zstd, runs **on the
|
||
host**, outside the guest's memory: +1.1 GB of host memory. On an 8 GB box the host keeps about 4 GB (box − guest), so it
|
||
fits there. So the backups use a small part of the headroom; on this box the headroom was really used by the apps' own
|
||
peaks working at once (R1) — and on 4 GB that is not enough (R3).
|
||
|
||
## R4 — second opinions for the weakest figures (evidence `evidence/R4-b1..b4/`, `summary.json` from the sizing run's `analyze.py`)
|
||
|
||
The 24 weakest page figures (`apps-table.json`: source `onboarding` or `telemetry` **and** the sources disagree): 3 were
|
||
measured in R1 (immich, nextcloud, vaultwarden), 5 are the box's own apps (table above), the other **16** ran here in four
|
||
batches on scratch guest 9202 at full memory (06:00–07:25 UTC): deployed through the product, 15 min at rest, removed
|
||
(no leftovers). These are **light batches — no action** (as the sizing run's light batches): the rest figure is a fair
|
||
second opinion; the „peak" here is only the start-up peak, so a page peak that includes real work reads higher.
|
||
|
||
| App | Page source | Page typical | HP rest | Diff | Page peak | HP peak (rest batch, no action) | Diff | OOM |
|
||
|---|---|---|---|---|---|---|---|---|
|
||
| grafana | onboarding | 220 | 269 | +22 % | 435 | 383 | -12 % | 0 |
|
||
| grimmory | onboarding | 346 | 451 | **+30 %** | 1095 | 624 | -43 % | 0 |
|
||
| karakeep | onboarding | 361 | 372 | +3 % | 1050 | 643 | -39 % | 0 |
|
||
| mealie | onboarding | 273 | 226 | -17 % | 431 | 240 | -44 % | 0 |
|
||
| n8n | onboarding | 321 | 351 | +9 % | 550 | 578 | +5 % | 0 |
|
||
| sparkyfitness | onboarding | 305 | 316 | +4 % | 664 | 410 | -38 % | 0 |
|
||
| uptime-kuma | onboarding | 103 | 118 | +15 % | 227 | 119 | -48 % | 0 |
|
||
| wishlist | onboarding | 115 | 118 | +3 % | 184 | 121 | -34 % | 0 |
|
||
| crafty-controller | onboarding | 78 | 79 | +1 % | 84 | 80 | -5 % | 0 |
|
||
| emby | onboarding | 142 | 136 | -4 % | 146 | 142 | -3 % | 0 |
|
||
| gitea | onboarding | 74 | 76 | +3 % | 136 | 89 | -35 % | 0 |
|
||
| grocy | onboarding | 30 | 33 | +10 % | 114 | 34 | -70 % | 0 |
|
||
| lubelogger | onboarding | 53 | 56 | +6 % | 113 | 65 | -42 % | 0 |
|
||
| metube | onboarding | 62 | 62 | +0 % | 329 | 63 | -81 % | 0 |
|
||
| qbittorrent | onboarding | 163 | 18 | **-89 %** | 318 | 18 | -94 % | 0 |
|
||
| transmission | onboarding | 6 | 6 | +0 % | 22 | 7 | -68 % | 0 |
|
||
|
||
At rest, 14 of 16 agree within ±30 %. Two differ: **grimmory +30 %** (451 vs 346) and **qbittorrent −89 %** (18 vs 163 —
|
||
idle with no torrent; the page's figure is from a household's onboarding note with torrents running, so the HP figure is
|
||
the weaker one here). No OOM kill.
|
||
|
||
## Apps that differ from the page by more than 30 % (one line each)
|
||
|
||
| App | Figure | Page | HP | Basis |
|
||
|---|---|---|---|---|
|
||
| nextcloud | peak | 525 | 290 (−45 %) | 50 × 10 MiB upload, alone and with others |
|
||
| vaultwarden | peak | 99 | 40 (−60 %) | light use |
|
||
| home-assistant | peak | 328 | 434 (+32 %) | the start after a boot |
|
||
| calibre-web | peak | 413 | 242 (−41 %) | the box's own, all night |
|
||
| grimmory | typical | 346 | 451 (+30 %) | rest batch |
|
||
| qbittorrent | typical | 163 | 18 (−89 %) | rest batch, no torrents |
|
||
| bentopdf | typical / peak | 5 / 10 | 10 / 15 | +5 MB only |
|
||
|
||
## Proposal — for the operator; nothing on the website changed tonight
|
||
|
||
**One answerable question:** should the page's figures move with tonight's measurements?
|
||
|
||
| Option | What changes | Cost | If nothing is done |
|
||
|---|---|---|---|
|
||
| **A (recommended)** — small figure update | Immich peak 3,061 → 3,300; Jellyfin peak 373 → 450; Home Assistant peak 328 → 435; Nextcloud peak 525 → 300; Vaultwarden peak 99 → 45; Grimmory typical 346 → 450. Keep the headroom (1.5), the platform (470) and every verdict | one data edit + the page's data file rebuilt; the „Family starter set" peak moves +144 MB (5,515 → 5,659): its verdicts stay (8 GB no, 12 GB tight, 16 GB well) | the page stays inside ±10 % for the family set; three apps keep a peak that reads low |
|
||
| B — also a sentence for Immich on 8 GB | „Immich works on 8 GB, but its face and search jobs restart under memory pressure" next to the „tight" verdict | one string in two languages | a household on 8 GB with Immich sees slow, restarting background jobs with no explanation |
|
||
|
||
**The three answers on an 8 GB box were all true** (R3): files + passwords fit well (0 OOM kills), Immich alone is tight
|
||
(it works; 14 OOM kills in its ML container, swap full), the family set does not fit (84 of 200 photo uploads failed,
|
||
transcode 15× slower, Paperless did nothing in 30 min). The headroom of 1.5 is not too strict: the family set's real
|
||
simultaneous peak was 97 % of the page's sum. Register row R-1009.
|
||
|
||
## 2026-10-14 — the operator's „raise only" ruling, built and STOPPED before the push
|
||
|
||
The rule was built as a source (`raise-only-source.patch` for `sizing-2026-10-13/tools/build_sizing.py`; the HP figures
|
||
from the evidence by `tools/hp_figures.py` → `hp-figures.json`, 27 apps, `used` basis). It raises 23 figures and lowers none
|
||
(Immich typical 1,356 → 1,557 and peak 3,061 → 3,290; Jellyfin peak 373 → 448; Home Assistant 318 → 352 / 328 → 434;
|
||
Paperless 568 → 645 / 659 → 755; Grimmory typical 346 → 451; and 17 small ones). The presets keep their verdicts (family
|
||
5,515 → 6,021 MB: 8 GB no, 12 GB tight, 16 GB well; files + passwords 1,094 unchanged; Immich alone 3,531 → 3,760: 8 GB tight).
|
||
|
||
**But one verdict of the `SIZING.md` §5 table changes:** „Household set without Immich" on 8 GB — **fits well → fits, but
|
||
tight**. Its peak becomes 2,731 MB; × 1.5 = 4,096.5 MB against the 8 GB guest's 4,096 MB: **0.5 MB over**. Not one figure
|
||
does it: without the Jellyfin raise, or the Home Assistant raise, or the Paperless raise, it stays „fits well". By the
|
||
task's STOP rule the website was **not** pushed; the data changes were reverted (nothing half-built is committed).
|
||
|
||
| Option | What happens | Cost |
|
||
|---|---|---|
|
||
| A — publish the raise as ruled; accept the one changed verdict | „5 apps without Immich on 8 GB" reads „fits, but tight"; `SIZING.md` §5 and the test case updated | the page is 0.5 MB pessimistic there |
|
||
| B — raise only, but round the HP figures to the nearest 10 MB **down** | to be checked: it may still flip | one rule sentence |
|
||
| C — keep today's figures | nothing changes; the HP's higher figures stay unused | the page reads low for Immich, Jellyfin, Home Assistant, Paperless |
|
||
|