WIP: measure option B first-fill map and paged startup (#792) #953

Closed
kayg wants to merge 1 commit from perf/tiering-option-b into dev
Owner

Option B identity prototype

Build on dev without changing storage layout. Reuse dev's compact identity map and log writer for a Home's first scan; after discovery publish the paged projection once, then release the map. Reuse the existing projection recovery and bounded writer from #792. Warm startup classifies paths by one ordered projection traversal, rather than point queries for every file. This prototype is not a tiering rollout.

Sizes and costs

Measure 1k, 10k, 100k notes and the plan's 10M aggregate identity envelope (100 Homes of 100k, ten active), including the 1M active envelope separately. Notes average 4 KiB; retain the harness's deterministic mixed-size distribution for comparison with A. First fill uses O(N + path bytes) transient heap, the same map as dev. Projection construction is O(N log N), one FULL transaction with secondary indexes built afterwards. Publication also streams the authoritative log before replay and before install, O(L) work for L authoritative-log bytes, with constant hash memory, so an equal-length rewrite in one filesystem clock tick cannot certify a stale projection. Normal ID lookups and writes are O(log N); pages use O(log N + page size); startup classification sorts observed paths O(N log N) and merges them with one O(N) ordered projection pass. Report sorting and projection time as well as total startup.

Reuse current paged connection/cache/admission limits, explicitly report any mismatch with the approved 64 MiB aggregate cache gate. Do not silently replace a failed B scale case with A. The 50 MiB transient allowance is a measured delta, not a capacity claim. Initial scope is one Home at a time; concurrent first fills and the full aggregate envelope remain gates, not implied passes.

Failure table

Failure Effect Detection Recovery Test
Process exits before projection publication Log retains acknowledged identities Log identity/length differs from projection Replay log once, FULL transaction reopen before publication
Projection publication fails Keep map available; no successful switch Returned SQLite/I/O error and scan health Restart and rebuild from log invalid projection destination
Paged writer refuses discovery admission Discovery stays incomplete; accepted mappings still publish their metadata Awaited admission error Retry when capacity returns; restart after writer failure held full queue, refused discovery, retry
Interrupted projection transaction No partial committed view SQLite recovery and watermark Rebuild from durable log inherited projection crash tests
Equal-length log rewrite during publication Reject stale candidate even when timestamps collide Streamed content digest before replay and install Retain map, retry publication from current log forced timestamp-collision rewrite
Update or deletion during first fill Newest map/log entry wins Identity answers before and after switch Serialize switch with index guard rename/delete/shadow switch regression
Outside change at startup Changed/unknown/vanished classification Ordered merge and saved file stamps Existing reconcile path compare merge with independent map
RSS/latency/scale gate fails Prototype rejected for acceptance Locked ABAB and dev control Keep draft; report failure perf matrix

Execution and gates

  1. Functional switch/reopen and startup-merge tests first; run on dev-01 through Nix/slot. Build the smallest index-only change and preserve unrelated dev code.
  2. Format, strict clippy, workspace tests and release binaries on dev-01 only. Push atomic commits immediately.
  3. Transfer binaries through control, verify SHA256. Hold perf-01 then perf-02 shared locks together. Run ABAB head/dev, then dev/dev control in the same session, at 1k/10k/100k plus the largest approved envelope. Measure fill and startup peak/steady RSS, first page, fill including projection publication, startup check, reads, saves, list and search both during startup and settled.
  4. Every touched hot path must be flat or better than dev. Keep all existing budgets including 100k fill <=60 s, first page <=100 ms, open p95 <=15 ms, idle RSS <=100 MB and the 64 MiB global cache bound. Failed, noisy or unrun gates do not pass. Post results and exact commands only as PR comments. Remove seeded Homes/targets and release both locks. Never merge.
# Option B identity prototype Build on dev without changing storage layout. Reuse dev's compact identity map and log writer for a Home's first scan; after discovery publish the paged projection once, then release the map. Reuse the existing projection recovery and bounded writer from #792. Warm startup classifies paths by one ordered projection traversal, rather than point queries for every file. This prototype is not a tiering rollout. ## Sizes and costs Measure 1k, 10k, 100k notes and the plan's 10M aggregate identity envelope (100 Homes of 100k, ten active), including the 1M active envelope separately. Notes average 4 KiB; retain the harness's deterministic mixed-size distribution for comparison with A. First fill uses O(N + path bytes) transient heap, the same map as dev. Projection construction is O(N log N), one FULL transaction with secondary indexes built afterwards. Publication also streams the authoritative log before replay and before install, O(L) work for L authoritative-log bytes, with constant hash memory, so an equal-length rewrite in one filesystem clock tick cannot certify a stale projection. Normal ID lookups and writes are O(log N); pages use O(log N + page size); startup classification sorts observed paths O(N log N) and merges them with one O(N) ordered projection pass. Report sorting and projection time as well as total startup. Reuse current paged connection/cache/admission limits, explicitly report any mismatch with the approved 64 MiB aggregate cache gate. Do not silently replace a failed B scale case with A. The 50 MiB transient allowance is a measured delta, not a capacity claim. Initial scope is one Home at a time; concurrent first fills and the full aggregate envelope remain gates, not implied passes. ## Failure table | Failure | Effect | Detection | Recovery | Test | |---|---|---|---|---| | Process exits before projection publication | Log retains acknowledged identities | Log identity/length differs from projection | Replay log once, FULL transaction | reopen before publication | | Projection publication fails | Keep map available; no successful switch | Returned SQLite/I/O error and scan health | Restart and rebuild from log | invalid projection destination | | Paged writer refuses discovery admission | Discovery stays incomplete; accepted mappings still publish their metadata | Awaited admission error | Retry when capacity returns; restart after writer failure | held full queue, refused discovery, retry | | Interrupted projection transaction | No partial committed view | SQLite recovery and watermark | Rebuild from durable log | inherited projection crash tests | | Equal-length log rewrite during publication | Reject stale candidate even when timestamps collide | Streamed content digest before replay and install | Retain map, retry publication from current log | forced timestamp-collision rewrite | | Update or deletion during first fill | Newest map/log entry wins | Identity answers before and after switch | Serialize switch with index guard | rename/delete/shadow switch regression | | Outside change at startup | Changed/unknown/vanished classification | Ordered merge and saved file stamps | Existing reconcile path | compare merge with independent map | | RSS/latency/scale gate fails | Prototype rejected for acceptance | Locked ABAB and dev control | Keep draft; report failure | perf matrix | ## Execution and gates 1. Functional switch/reopen and startup-merge tests first; run on dev-01 through Nix/slot. Build the smallest index-only change and preserve unrelated dev code. 2. Format, strict clippy, workspace tests and release binaries on dev-01 only. Push atomic commits immediately. 3. Transfer binaries through control, verify SHA256. Hold perf-01 then perf-02 shared locks together. Run ABAB head/dev, then dev/dev control in the same session, at 1k/10k/100k plus the largest approved envelope. Measure fill and startup peak/steady RSS, first page, fill including projection publication, startup check, reads, saves, list and search both during startup and settled. 4. Every touched hot path must be flat or better than dev. Keep all existing budgets including 100k fill <=60 s, first page <=100 ms, open p95 <=15 ms, idle RSS <=100 MB and the 64 MiB global cache bound. Failed, noisy or unrun gates do not pass. Post results and exact commands only as PR comments. Remove seeded Homes/targets and release both locks. Never merge.
docs: plan measured option B identity prototype
Some checks failed
CI / web (pull_request) Has been cancelled
Markdown extraction contract / markdown-native-contract (pull_request) Has been cancelled
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
Markdown extraction contract / markdown-editor-contract (pull_request) Has been cancelled
b67f99af99
Author
Owner

validation checkpoint, not an option b performance result:

  • the prototype is pushed, and rustfmt ran on dev-01. compilation, functional checks, clippy and release builds remain queued through the existing slot scheduler behind a live train reservation. no reservation was bypassed.
  • a locked 1k dev/dev-copy smoke check validated the external measurement driver: four arms, 200 verified appends per arm, complete settled search results, and seeded Homes removed afterward. this calibration does not qualify b. both perf lock holders were stopped.
  • static review found that warm discovery drops identity acknowledgements even though the reused paged writer can refuse admission. a deterministic regression test now fills the held writer queue and requires discovery to expose that refusal. it is queued before the fix.
  • the 100×100k qualification envelope remains required; a single 1m-note Home is not a substitute. allocated disk footprints will determine whether that envelope can be seeded while retaining the required free space.
  • the inherited projection lease/cache configuration permits 704 MiB aggregate SQLite page caches. that is a configured bound, not measured consumption, and does not satisfy the approved 64 MiB bound. the gate is unchanged.

b has no measured performance verdict yet and remains unaccepted. results and exact commands will be added here after the build and perf runs.

validation checkpoint, not an option b performance result: - the prototype is pushed, and rustfmt ran on dev-01. compilation, functional checks, clippy and release builds remain queued through the existing slot scheduler behind a live train reservation. no reservation was bypassed. - a locked 1k dev/dev-copy smoke check validated the external measurement driver: four arms, 200 verified appends per arm, complete settled search results, and seeded Homes removed afterward. this calibration does not qualify b. both perf lock holders were stopped. - static review found that warm discovery drops identity acknowledgements even though the reused paged writer can refuse admission. a deterministic regression test now fills the held writer queue and requires discovery to expose that refusal. it is queued before the fix. - the 100×100k qualification envelope remains required; a single 1m-note Home is not a substitute. allocated disk footprints will determine whether that envelope can be seeded while retaining the required free space. - the inherited projection lease/cache configuration permits 704 MiB aggregate SQLite page caches. that is a configured bound, not measured consumption, and does not satisfy the approved 64 MiB bound. the gate is unchanged. b has no measured performance verdict yet and remains unaccepted. results and exact commands will be added here after the build and perf runs.
Author
Owner

functional checkpoint at 13:40 ist, still no option b perf result:

  • dev-01 tob-check4 reproduced the admission bug: cargo test -j4 -p calternal-notes warm_discovery_surfaces_refused_identity_admission --locked -- --nocapture failed with discovery hid a refused identity admission.
  • after the bounded acknowledgement fix, tob-check5 passed notes all-target compilation, that regression (1 passed), and cargo test -j4 -p calternal-notes option_b_tests --locked -- --nocapture (6 passed). rustfmt passed.
  • strict workspace clippy then found one needless borrow in bulk import. commit 40795a38 removes it. full validation of the latest head 9b7fad0934aa5a7151e4fb47532290867a501454 and its release build are now queued through nix/slot behind the live dev-01 train. no train reservation was bypassed.
  • no b binary has been measured. the 50 mib transient allowance and every runtime gate remain unqualified. the inherited 704 mib configured cache bound still fails the approved 64 mib bound.

results, scripts and exact measurement commands will stay in pr comments. no acceptance or merge is implied by this checkpoint.

functional checkpoint at 13:40 ist, still no option b perf result: - dev-01 `tob-check4` reproduced the admission bug: `cargo test -j4 -p calternal-notes warm_discovery_surfaces_refused_identity_admission --locked -- --nocapture` failed with `discovery hid a refused identity admission`. - after the bounded acknowledgement fix, `tob-check5` passed notes all-target compilation, that regression (1 passed), and `cargo test -j4 -p calternal-notes option_b_tests --locked -- --nocapture` (6 passed). rustfmt passed. - strict workspace clippy then found one needless borrow in bulk import. commit `40795a38` removes it. full validation of the latest head `9b7fad0934aa5a7151e4fb47532290867a501454` and its release build are now queued through nix/slot behind the live dev-01 train. no train reservation was bypassed. - no b binary has been measured. the 50 mib transient allowance and every runtime gate remain unqualified. the inherited 704 mib configured cache bound still fails the approved 64 mib bound. results, scripts and exact measurement commands will stay in pr comments. no acceptance or merge is implied by this checkpoint.
Author
Owner

latest-build measurement checkpoint, no acceptance verdict yet:

  • head 3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 release build passed on dev-01 through nix/slot. binary sha256 e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c matches on dev-01, control and perf-01. dev is 9377d711217532a44973edcf63c2af0b7f7969d8, binary e7fce554632c7a35dd6fc424fd55f29a86377f04d12228141b23037b8176f5d5.
  • perf-01 was confirmed acquired before requesting perf-02; both are held together. the final-build run uses a new report root ~/tob-b2. an earlier partial run used a different binary and was stopped, its active Home removed, and its results excluded from qualification.
  • matrix: sizes 1k/10k/100k, three dev/head/dev/head cycles per size, followed by dev/dev-copy/dev/dev-copy; fresh seeded Home per arm. decoded websocket reads and journal probes follow with the same arm order. allocator: glibc.malloc.arena_max=2; no page-cache drop. raw request samples, RSS series and every failure are retained.
  • full-fill time includes projection publication. RSS records sampled peaks plus kernel VmHWM, at discovery, after publication, at warm-check completion and after settled work. a separate 720-second idle campaign remains required.
  • report medians across arms, plus observed peak maxima and every relative hot-path delta with the contemporaneous dev-copy control. noisy, failed or unrun gates do not pass. the 50 mib comparison will use measured process RSS, with no claim that unrelated startup allocations are identity-map memory.
  • the previous workspace run passed 590 notes tests with one restart-fixture loop failure; that loop now continues on the reopened server, preserving its byte/version/idempotency assertions. full latest-head checks are queued through the existing train reservation. the deterministic same-timestamp log rewrite now passes with streamed content verification.
  • the 100×100k envelope and the 64 mib global cache bound remain unchanged. the inherited configured cache allowance is still 704 mib, a failed bound rather than measured consumption. no merge.

commands and the completed tables will follow with the raw artifacts.

latest-build measurement checkpoint, no acceptance verdict yet: - head `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1` release build passed on dev-01 through nix/slot. binary sha256 `e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c` matches on dev-01, control and perf-01. dev is `9377d711217532a44973edcf63c2af0b7f7969d8`, binary `e7fce554632c7a35dd6fc424fd55f29a86377f04d12228141b23037b8176f5d5`. - perf-01 was confirmed acquired before requesting perf-02; both are held together. the final-build run uses a new report root `~/tob-b2`. an earlier partial run used a different binary and was stopped, its active Home removed, and its results excluded from qualification. - matrix: sizes 1k/10k/100k, three dev/head/dev/head cycles per size, followed by dev/dev-copy/dev/dev-copy; fresh seeded Home per arm. decoded websocket reads and journal probes follow with the same arm order. allocator: `glibc.malloc.arena_max=2`; no page-cache drop. raw request samples, RSS series and every failure are retained. - full-fill time includes projection publication. RSS records sampled peaks plus kernel VmHWM, at discovery, after publication, at warm-check completion and after settled work. a separate 720-second idle campaign remains required. - report medians across arms, plus observed peak maxima and every relative hot-path delta with the contemporaneous dev-copy control. noisy, failed or unrun gates do not pass. the 50 mib comparison will use measured process RSS, with no claim that unrelated startup allocations are identity-map memory. - the previous workspace run passed 590 notes tests with one restart-fixture loop failure; that loop now continues on the reopened server, preserving its byte/version/idempotency assertions. full latest-head checks are queued through the existing train reservation. the deterministic same-timestamp log rewrite now passes with streamed content verification. - the 100×100k envelope and the 64 mib global cache bound remain unchanged. the inherited configured cache allowance is still 704 mib, a failed bound rather than measured consumption. no merge. commands and the completed tables will follow with the raw artifacts.
Author
Owner

option b main campaign results, 5 november, 15:23 ist. b does not qualify for adoption.

head 3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1, dev 9377d711217532a44973edcf63c2af0b7f7969d8. exact head binary sha256 e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c; dev binary e7fce554632c7a35dd6fc424fd55f29a86377f04d12228141b23037b8176f5d5. no cache drop. both shared perf locks were held together, perf-01 confirmed acquired before perf-02. measurements ran on perf-01. both holders were stopped after the campaign.

48 custom arms completed, 16 per size: three dev/b/dev/b cycles, then dev/dev-copy/dev/dev-copy. native websocket/journal harness completed 16 arms, each covering all three sizes, with three warm runs per arm and one cold run. no custom failure files and no native recorded failures. medians below are medians of arm quantiles, not pooled quantiles. control columns are the same-session dev-copy/dev ratio; do not subtract this ratio from b's results or use it to waive regressions. raw request samples and arm ranges will be attached.

full-fill timing includes projection publication. the first-page metric is the first notes.list response after health readiness, including lazy Home open; the native harness also reports cold.first_page and warm home.first_page separately. startup-check timing is observed completion during early requests, with a 20 ms polling interval. RSS uses the child process only: 10 ms samples plus kernel VmHWM. steady fill is sampled two seconds after publication; startup steady follows the settled request campaign. the 720-second idle campaign is separate and still running. native mem.idle here uses --idle-secs 0 and is not the 720-second idle gate.

notes b/dev fill peak maximum, mib b/dev warm-check peak maximum, mib largest paired b-minus-dev fill peak, mib largest paired b-minus-dev check peak, mib
1k 47.344 / 46.984 26.664 / 26.535 +1.266 +0.980
10k 144.805 / 145.008 42.016 / 43.145 +0.883 +2.574
100k 298.324 / 296.160 126.188 / 129.840 +6.305 +6.348

the tested single-Home paired peak excess is below 50 mib in every arm. this measures total process RSS differences, not isolated map allocation, and does not qualify concurrent first fills or the full aggregate envelope.

internal b timings, six arms each:

notes one projection publication median (range), ms sort median, ms ordered merge median, ms
1k 51.5 (51–58) 0.067 0.881
10k 93 (89–95) 0.869 12.593
100k 579.5 (573–608) 11.437 125.045

current gate verdicts: 100k fill <=60 s passes its absolute budget; cold first-page <=100 ms fails; native open.note p95 <=15 ms passes its absolute budget. the requirement that every touched hot path be flat or better fails qualification: for example, settled 100k append p95 is 14.721 ms versus 12.107 ms (+21.6%; dev-copy control +10.9%), settled 1k create is 31.065 versus 22.856 ms (+35.9%; control +9.9%), and 10k native api-get p95 is 10.121 versus 7.477 ms (+35.4%; control -11.4%). noisy paths also cannot pass. startup-check and publication overhead are included and reported below. the inherited 704 mib configured aggregate cache allowance fails the unchanged 64 mib bound. idle, concurrent first fills, and the 100×100k/ten-active envelope remain unqualified pending the remaining measurements and feasibility check. no gate was loosened. functional final-head checks are still queued behind the existing dev-01 reservation.

exact measurement commands, using the attached unchanged scripts:

# holder command, first on perf-01; confirm ready before requesting perf-02
systemd-run --user --unit=tob-measure-hold --collect -p RuntimeMaxSec=10800 \
  ~/bin/perf-lock bash -c 'date -u +%s > "$HOME/tob-lock-6c.ready"; sleep 7200'

TOB_ROOT="$HOME/tob-b2" \
TOB_HEAD_SHA=3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 \
TOB_DEV_SHA=9377d711217532a44973edcf63c2af0b7f7969d8 \
python3 "$HOME/tob/measure.py" --sizes 1000,10000,100000 --cycles 3
TOB_ROOT="$HOME/tob-b2" bash "$HOME/tob/native.sh"
# native.sh uses each arm's exact binary with:
PERF_ONLY=list,query,journal,open GLIBC_TUNABLES=glibc.malloc.arena_max=2 \
  "$B/calternal-perf-filtered" --bin "$B/calternal-$arm" --work "$work" \
  --sizes 1k,10k,100k --runs 3 --cold-runs 1 --seed 1 --idle-secs 0 \
  --json "$R/$label.json" --md "$R/$label.md"
# stop on both hosts
systemctl --user stop tob-measure-hold.service

all VM access used timeout 60 netbird ssh claude@calternal-perf-01-backup01.vpn.kayg.org '<command>' or the corresponding perf-02 address. the custom driver sets CALTERNAL_NOTES_SAVE_MS=15 and GLIBC_TUNABLES=glibc.malloc.arena_max=2. script sha256 ab2176240bb0f4894ccd9689aa803ea45832064d9cc59f386d1c5609795beaf5; filtered native harness sha256 352d448a4e7ef2c8099eb38ad02fd2fea2be93b6f7cba6bc83d29bf3cd7ce374.

full tables follow. RSS values labelled MB by the native harness are its original labels; custom process values are mib. every early/settled p50/p95 delta and native metric is retained, including regressions.

medians across complete arms; control uses the same-session dev-copy arms. raw failures remain failures.

1000 notes, process

metric unit b dev b/dev copy/dev control delta
first_page_ms ms 307.816 302.432 1.018 0.951 5.384
first_fill_discovery_ms ms 359.362 353.950 1.015 0.957 5.412
first_fill_with_projection_ms ms 379.553 354.056 1.072 0.957 25.497
startup_ready_ms ms 21.227 21.297 0.997 0.992 -0.070
startup_check_ms ms 22.175 24.416 0.908 1.466 -2.241
fill.vmhwm_mib MiB 47.121 46.861 1.006 0.996 0.260
fill.steady_rss_mib MiB 30.781 39.582 0.778 1.099 -8.801
startup_check_peak_rss_mib MiB 26.406 26.213 1.007 1.050 0.193
rss_at_check_complete_mib MiB 26.320 25.959 1.014 1.063 0.361
startup.vmhwm_mib MiB 50.068 48.969 1.022 1.002 1.100
startup.steady_rss_mib MiB 45.654 45.389 1.006 1.023 0.266
materialized_home_allocated_bytes bytes 53030912.000 48490496.000 1.094 1.000 4540416.000

1000 notes, early

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 7.991 7.911 1.010 0.991 0.080
list.big.p95_ms ms 8.754 8.972 0.976 0.973 -0.218
list.next.p50_ms ms 0.884 0.872 1.014 1.092 0.012
list.next.p95_ms ms 0.966 0.940 1.027 1.125 0.026
list.page.p50_ms ms 1.034 1.038 0.997 1.022 -0.003
list.page.p95_ms ms 1.236 1.259 0.982 1.015 -0.023
list.tag.p50_ms ms 1.487 1.470 1.011 1.005 0.017
list.tag.p95_ms ms 1.698 1.761 0.964 0.867 -0.063
list.title.p50_ms ms 0.793 0.796 0.996 1.023 -0.003
list.title.p95_ms ms 0.957 0.961 0.996 0.941 -0.004
read.api.p50_ms ms 4.933 4.874 1.012 0.992 0.058
read.api.p95_ms ms 5.877 5.719 1.028 1.022 0.159
save.append.p50_ms ms 5.537 5.518 1.004 1.009 0.020
save.append.p95_ms ms 15.262 15.060 1.013 1.139 0.202
save.create.p50_ms ms 21.916 16.803 1.304 1.020 5.113
save.create.p95_ms ms 37.108 22.203 1.671 0.950 14.906
save.delete.p50_ms ms 41.071 36.739 1.118 1.026 4.332
save.delete.p95_ms ms 46.245 42.007 1.101 0.943 4.238
save.rename.p50_ms ms 24.158 19.691 1.227 1.017 4.467
save.rename.p95_ms ms 28.985 22.921 1.265 0.863 6.064
save.restore.p50_ms ms 12.176 10.183 1.196 1.028 1.993
save.restore.p95_ms ms 14.241 11.928 1.194 1.115 2.313
search.query.p50_ms ms 0.597 0.443 1.350 0.908 0.155
search.query.p95_ms ms 9.752 8.250 1.182 1.250 1.502
200 append total ms 1152.734 1149.311 1.003 1.035 3.423

1000 notes, settled

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 8.631 8.669 0.996 1.011 -0.038
list.big.p95_ms ms 9.398 9.239 1.017 0.973 0.160
list.next.p50_ms ms 0.957 0.925 1.035 0.933 0.032
list.next.p95_ms ms 1.076 1.013 1.063 0.956 0.064
list.page.p50_ms ms 1.137 1.098 1.036 1.005 0.039
list.page.p95_ms ms 1.377 1.422 0.968 0.957 -0.045
list.tag.p50_ms ms 1.574 1.573 1.001 0.976 0.001
list.tag.p95_ms ms 1.765 1.786 0.988 0.958 -0.021
list.title.p50_ms ms 0.882 0.874 1.009 0.990 0.008
list.title.p95_ms ms 1.029 1.043 0.987 0.988 -0.014
read.api.p50_ms ms 0.338 0.301 1.123 1.063 0.037
read.api.p95_ms ms 0.397 0.392 1.013 1.031 0.005
save.append.p50_ms ms 3.923 3.908 1.004 0.979 0.015
save.append.p95_ms ms 17.406 17.919 0.971 1.119 -0.512
save.create.p50_ms ms 21.829 16.934 1.289 0.980 4.895
save.create.p95_ms ms 31.065 22.856 1.359 1.099 8.208
save.delete.p50_ms ms 41.154 36.797 1.118 0.990 4.357
save.delete.p95_ms ms 45.612 42.103 1.083 0.970 3.509
save.rename.p50_ms ms 24.239 19.950 1.215 0.990 4.290
save.rename.p95_ms ms 28.895 27.998 1.032 0.971 0.896
save.restore.p50_ms ms 12.215 10.242 1.193 0.975 1.973
save.restore.p95_ms ms 16.765 11.255 1.490 0.756 5.509
search.query.p50_ms ms 1.557 1.552 1.003 1.113 0.005
search.query.p95_ms ms 2.573 2.540 1.013 1.066 0.033
200 append total ms 1056.900 1096.858 0.964 0.969 -39.958

1000 notes, native

metric unit b dev b/dev copy/dev control delta
cold.disk_written.p50 MB 19.292 18.780 1.027 0.999 0.512
cold.disk_written.p95 MB 19.292 18.780 1.027 0.999 0.512
cold.first_page.p50 ms 361.492 380.538 0.950 1.027 -19.046
cold.first_page.p95 ms 361.492 380.538 0.950 1.027 -19.046
cold.index.p50 s 0.464 0.483 0.961 1.022 -0.019
cold.index.p95 s 0.464 0.483 0.961 1.022 -0.019
cold.mem_peak.p50 MB 46.510 46.592 0.998 1.001 -0.082
cold.mem_peak.p95 MB 46.510 46.592 0.998 1.001 -0.082
cold.notes_per_s.p50 notes/s 2156.430 2071.669 1.041 0.979 84.761
cold.notes_per_s.p95 notes/s 2156.430 2071.669 1.041 0.979 84.761
cold.startup.p50 ms 16.504 17.756 0.930 0.936 -1.252
cold.startup.p95 ms 16.504 17.756 0.930 0.936 -1.252
home.first_page.p50 ms 1.754 2.054 0.854 0.638 -0.300
home.first_page.p95 ms 2.730 3.676 0.743 0.657 -0.947
home.page.p50 ms 0.708 0.689 1.027 1.036 0.019
home.page.p95 ms 1.445 1.527 0.946 0.738 -0.082
home.page_big.p50 ms 7.989 7.989 1.000 0.990 -0.000
home.page_big.p95 ms 8.611 8.550 1.007 1.033 0.061
home.page_next.p50 ms 0.726 0.740 0.981 0.938 -0.014
home.page_next.p95 ms 0.788 0.803 0.981 0.965 -0.015
home.page_tag.p50 ms 1.224 1.250 0.979 0.986 -0.026
home.page_tag.p95 ms 1.358 1.394 0.974 0.951 -0.036
home.page_title.p50 ms 0.597 0.589 1.013 0.926 0.008
home.page_title.p95 ms 0.685 0.701 0.978 0.824 -0.016
journal.catch_up.p50 ms 2.984 2.918 1.023 0.990 0.066
journal.catch_up.p95 ms 3.442 3.203 1.075 0.981 0.239
journal.entries.p50 count 1000.000 1000.000 1.000 1.000 0.000
journal.entries.p95 count 1000.000 1000.000 1.000 1.000 0.000
journal.page.p50 ms 2.727 2.663 1.024 0.989 0.064
journal.page.p95 ms 3.178 2.928 1.085 0.983 0.250
mem.after_first_page.p50 MB 21.967 21.842 1.006 0.989 0.125
mem.after_first_page.p95 MB 22.244 22.131 1.005 0.980 0.113
mem.after_opens.p50 MB 35.271 34.504 1.022 0.990 0.768
mem.after_opens.p95 MB 35.420 34.773 1.019 1.005 0.646
mem.idle.p50 MB 19.205 19.133 1.004 1.025 0.072
mem.idle.p95 MB 19.748 19.672 1.004 1.015 0.076
open.api_get.p50 ms 6.105 5.850 1.044 1.055 0.255
open.api_get.p95 ms 10.002 9.552 1.047 1.081 0.450
open.long_note.p50 ms 15.333 15.140 1.013 0.860 0.193
open.long_note.p95 ms 44.672 44.887 0.995 1.058 -0.215
open.note.p50 ms 0.690 0.685 1.008 1.007 0.005
open.note.p95 ms 2.292 2.245 1.021 1.053 0.047
shutdown.p50 ms 42.948 42.678 1.006 0.999 0.271
shutdown.p95 ms 43.056 43.079 0.999 0.796 -0.023
startup.healthz.p50 ms 4.949 5.227 0.947 1.118 -0.279
startup.healthz.p95 ms 6.036 6.162 0.980 0.945 -0.126

10000 notes, process

metric unit b dev b/dev copy/dev control delta
first_page_ms ms 229.571 226.882 1.012 0.985 2.689
first_fill_discovery_ms ms 1370.830 1316.425 1.041 1.002 54.405
first_fill_with_projection_ms ms 1439.256 1316.638 1.093 1.002 122.618
startup_ready_ms ms 21.314 21.205 1.005 1.076 0.108
startup_check_ms ms 126.710 120.300 1.053 0.940 6.410
fill.vmhwm_mib MiB 143.875 144.436 0.996 1.002 -0.561
fill.steady_rss_mib MiB 56.686 137.666 0.412 0.989 -80.980
startup_check_peak_rss_mib MiB 41.543 40.707 1.021 0.981 0.836
rss_at_check_complete_mib MiB 38.070 37.172 1.024 0.963 0.898
startup.vmhwm_mib MiB 77.129 76.867 1.003 0.995 0.262
startup.steady_rss_mib MiB 58.607 60.143 0.974 1.035 -1.535
materialized_home_allocated_bytes bytes 238360576.000 230969344.000 1.032 1.000 7391232.000

10000 notes, early

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 16.566 17.257 0.960 0.999 -0.691
list.big.p95_ms ms 24.514 22.000 1.114 1.070 2.514
list.next.p50_ms ms 0.830 0.868 0.956 1.025 -0.038
list.next.p95_ms ms 0.963 0.974 0.989 0.948 -0.011
list.page.p50_ms ms 1.245 1.324 0.940 0.983 -0.079
list.page.p95_ms ms 2.004 2.040 0.982 0.978 -0.036
list.tag.p50_ms ms 5.405 5.498 0.983 1.015 -0.093
list.tag.p95_ms ms 6.665 6.811 0.979 1.047 -0.146
list.title.p50_ms ms 0.851 0.874 0.973 1.010 -0.023
list.title.p95_ms ms 1.025 1.148 0.892 0.923 -0.124
read.api.p50_ms ms 4.842 4.844 0.999 0.983 -0.003
read.api.p95_ms ms 6.928 5.197 1.333 1.303 1.731
save.append.p50_ms ms 5.418 5.402 1.003 0.992 0.016
save.append.p95_ms ms 15.837 16.796 0.943 1.051 -0.959
save.create.p50_ms ms 27.137 22.169 1.224 1.000 4.969
save.create.p95_ms ms 42.271 32.025 1.320 1.106 10.247
save.delete.p50_ms ms 41.463 36.766 1.128 0.997 4.697
save.delete.p95_ms ms 52.459 49.102 1.068 0.993 3.357
save.rename.p50_ms ms 35.575 31.074 1.145 0.989 4.500
save.rename.p95_ms ms 40.064 35.735 1.121 0.942 4.329
save.restore.p50_ms ms 12.233 10.155 1.205 1.007 2.078
save.restore.p95_ms ms 17.627 14.683 1.201 1.248 2.944
search.query.p50_ms ms 0.408 0.398 1.025 1.036 0.010
search.query.p95_ms ms 2.192 0.778 2.819 1.639 1.414
200 append total ms 1126.591 1127.146 1.000 1.012 -0.555

10000 notes, settled

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 17.665 18.179 0.972 1.055 -0.514
list.big.p95_ms ms 18.976 19.652 0.966 1.083 -0.676
list.next.p50_ms ms 0.898 0.886 1.014 1.058 0.012
list.next.p95_ms ms 1.019 1.033 0.986 0.977 -0.014
list.page.p50_ms ms 1.369 1.438 0.952 1.082 -0.068
list.page.p95_ms ms 1.618 1.668 0.970 0.864 -0.050
list.tag.p50_ms ms 5.477 5.624 0.974 1.053 -0.147
list.tag.p95_ms ms 5.995 6.113 0.981 1.058 -0.118
list.title.p50_ms ms 0.965 0.984 0.981 1.148 -0.019
list.title.p95_ms ms 1.151 1.237 0.930 1.142 -0.086
read.api.p50_ms ms 0.316 0.307 1.030 1.081 0.009
read.api.p95_ms ms 0.374 0.361 1.035 1.096 0.013
save.append.p50_ms ms 3.727 3.695 1.009 1.023 0.032
save.append.p95_ms ms 17.208 16.968 1.014 1.209 0.240
save.create.p50_ms ms 27.288 22.747 1.200 0.998 4.541
save.create.p95_ms ms 36.017 29.828 1.207 1.069 6.189
save.delete.p50_ms ms 40.874 37.052 1.103 1.006 3.822
save.delete.p95_ms ms 45.897 43.685 1.051 1.086 2.212
save.rename.p50_ms ms 35.772 31.890 1.122 0.989 3.882
save.rename.p95_ms ms 42.396 36.988 1.146 0.939 5.408
save.restore.p50_ms ms 12.082 10.312 1.172 1.009 1.770
save.restore.p95_ms ms 19.410 16.822 1.154 0.623 2.588
search.query.p50_ms ms 1.652 1.667 0.991 1.010 -0.015
search.query.p95_ms ms 4.261 4.222 1.009 1.061 0.039
200 append total ms 1011.121 985.155 1.026 1.024 25.965

10000 notes, native

metric unit b dev b/dev copy/dev control delta
cold.disk_written.p50 MB 150.112 150.163 1.000 1.004 -0.051
cold.disk_written.p95 MB 150.112 150.163 1.000 1.004 -0.051
cold.first_page.p50 ms 285.410 281.734 1.013 1.059 3.676
cold.first_page.p95 ms 285.410 281.734 1.013 1.059 3.676
cold.index.p50 s 1.414 1.411 1.002 1.047 0.003
cold.index.p95 s 1.414 1.411 1.002 1.047 0.003
cold.mem_peak.p50 MB 143.934 144.816 0.994 1.007 -0.883
cold.mem_peak.p95 MB 143.934 144.816 0.994 1.007 -0.883
cold.notes_per_s.p50 notes/s 7072.257 7086.895 0.998 0.954 -14.638
cold.notes_per_s.p95 notes/s 7072.257 7086.895 0.998 0.954 -14.638
cold.startup.p50 ms 17.289 15.641 1.105 1.001 1.647
cold.startup.p95 ms 17.289 15.641 1.105 1.001 1.647
home.first_page.p50 ms 3.085 2.658 1.161 1.409 0.427
home.first_page.p95 ms 3.731 5.050 0.739 1.128 -1.319
home.page.p50 ms 0.721 0.774 0.931 1.058 -0.053
home.page.p95 ms 1.891 2.460 0.768 0.700 -0.570
home.page_big.p50 ms 16.457 16.815 0.979 1.010 -0.358
home.page_big.p95 ms 17.270 18.427 0.937 0.952 -1.157
home.page_next.p50 ms 0.735 0.752 0.977 1.029 -0.017
home.page_next.p95 ms 0.816 0.873 0.935 1.007 -0.057
home.page_tag.p50 ms 5.564 5.510 1.010 1.027 0.054
home.page_tag.p95 ms 8.202 7.594 1.080 0.968 0.609
home.page_title.p50 ms 0.686 0.686 0.999 1.095 -0.000
home.page_title.p95 ms 0.876 0.911 0.962 1.198 -0.035
journal.catch_up.p50 ms 28.180 28.815 0.978 1.016 -0.635
journal.catch_up.p95 ms 33.134 30.544 1.085 1.043 2.590
journal.entries.p50 count 10000.000 10000.000 1.000 1.000 0.000
journal.entries.p95 count 10000.000 10000.000 1.000 1.000 0.000
journal.page.p50 ms 2.517 2.534 0.993 1.012 -0.017
journal.page.p95 ms 2.798 3.191 0.877 1.083 -0.394
mem.after_first_page.p50 MB 22.312 21.982 1.015 1.002 0.330
mem.after_first_page.p95 MB 22.559 22.715 0.993 1.032 -0.156
mem.after_opens.p50 MB 43.145 41.672 1.035 1.023 1.473
mem.after_opens.p95 MB 43.543 42.828 1.017 0.999 0.715
mem.idle.p50 MB 19.102 19.195 0.995 1.003 -0.094
mem.idle.p95 MB 19.408 20.305 0.956 1.017 -0.896
open.api_get.p50 ms 4.801 4.850 0.990 0.863 -0.049
open.api_get.p95 ms 10.121 7.477 1.354 0.886 2.644
open.long_note.p50 ms 17.680 18.941 0.933 1.671 -1.262
open.long_note.p95 ms 46.764 46.046 1.016 1.041 0.718
open.note.p50 ms 0.763 0.738 1.033 0.993 0.024
open.note.p95 ms 4.181 4.085 1.023 0.968 0.095
shutdown.p50 ms 43.036 42.571 1.011 0.764 0.465
shutdown.p95 ms 43.171 43.091 1.002 1.005 0.081
startup.healthz.p50 ms 4.947 5.086 0.973 0.887 -0.140
startup.healthz.p95 ms 5.213 8.492 0.614 1.377 -3.279

100000 notes, process

metric unit b dev b/dev copy/dev control delta
first_page_ms ms 1620.156 1603.764 1.010 1.072 16.391
first_fill_discovery_ms ms 15107.703 15103.746 1.000 1.021 3.957
first_fill_with_projection_ms ms 15684.382 15103.999 1.038 1.021 580.383
startup_ready_ms ms 21.303 21.336 0.998 0.999 -0.033
startup_check_ms ms 1249.453 1184.274 1.055 1.011 65.179
fill.vmhwm_mib MiB 290.348 292.877 0.991 0.982 -2.529
fill.steady_rss_mib MiB 160.615 271.037 0.593 0.986 -110.422
startup_check_peak_rss_mib MiB 125.277 125.520 0.998 1.005 -0.242
rss_at_check_complete_mib MiB 93.348 96.477 0.968 0.967 -3.129
startup.vmhwm_mib MiB 125.375 135.914 0.922 0.966 -10.539
startup.steady_rss_mib MiB 114.705 126.773 0.905 0.981 -12.068
materialized_home_allocated_bytes bytes 2457296896.000 2419812352.000 1.015 1.000 37484544.000

100000 notes, early

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 20.310 20.462 0.993 0.995 -0.152
list.big.p95_ms ms 29.501 30.264 0.975 1.047 -0.763
list.next.p50_ms ms 0.843 0.861 0.979 0.993 -0.018
list.next.p95_ms ms 0.945 1.048 0.901 0.981 -0.103
list.page.p50_ms ms 1.639 1.624 1.009 0.959 0.015
list.page.p95_ms ms 2.600 2.873 0.905 0.720 -0.273
list.tag.p50_ms ms 53.551 52.274 1.024 1.008 1.277
list.tag.p95_ms ms 62.701 55.881 1.122 1.010 6.820
list.title.p50_ms ms 1.045 1.040 1.005 1.096 0.006
list.title.p95_ms ms 1.375 1.468 0.937 1.130 -0.093
read.api.p50_ms ms 5.888 4.833 1.218 1.008 1.055
read.api.p95_ms ms 8.999 5.825 1.545 0.677 3.175
save.append.p50_ms ms 5.632 5.083 1.108 0.901 0.549
save.append.p95_ms ms 15.926 14.413 1.105 0.982 1.513
save.create.p50_ms ms 86.617 80.699 1.073 1.002 5.918
save.create.p95_ms ms 95.927 86.261 1.112 1.018 9.666
save.delete.p50_ms ms 46.956 36.925 1.272 0.987 10.031
save.delete.p95_ms ms 56.869 58.399 0.974 0.956 -1.530
save.rename.p50_ms ms 164.966 159.962 1.031 1.000 5.004
save.rename.p95_ms ms 175.252 170.788 1.026 0.990 4.464
save.restore.p50_ms ms 14.166 10.336 1.371 0.980 3.830
save.restore.p95_ms ms 20.400 16.429 1.242 0.939 3.971
search.query.p50_ms ms 0.375 0.380 0.987 0.883 -0.005
search.query.p95_ms ms 0.596 0.597 0.997 0.428 -0.002
200 append total ms 1247.307 1126.605 1.107 1.019 120.702

100000 notes, settled

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 22.273 20.997 1.061 0.961 1.276
list.big.p95_ms ms 40.953 38.741 1.057 0.986 2.212
list.next.p50_ms ms 0.847 0.849 0.998 0.948 -0.001
list.next.p95_ms ms 0.972 0.968 1.005 0.851 0.004
list.page.p50_ms ms 1.640 1.531 1.071 0.999 0.109
list.page.p95_ms ms 5.038 6.081 0.828 0.987 -1.043
list.tag.p50_ms ms 74.510 54.532 1.366 1.092 19.978
list.tag.p95_ms ms 213.362 211.662 1.008 1.041 1.701
list.title.p50_ms ms 1.074 1.081 0.994 0.977 -0.007
list.title.p95_ms ms 4.211 3.575 1.178 1.211 0.636
read.api.p50_ms ms 0.334 0.317 1.055 0.942 0.017
read.api.p95_ms ms 0.417 0.405 1.031 0.967 0.013
save.append.p50_ms ms 3.726 3.594 1.037 0.971 0.132
save.append.p95_ms ms 14.721 12.107 1.216 1.109 2.614
save.create.p50_ms ms 85.000 82.158 1.035 1.011 2.841
save.create.p95_ms ms 92.096 90.358 1.019 1.016 1.739
save.delete.p50_ms ms 41.143 37.413 1.100 1.007 3.730
save.delete.p95_ms ms 52.808 45.949 1.149 0.946 6.859
save.rename.p50_ms ms 171.418 184.557 0.929 1.131 -13.139
save.rename.p95_ms ms 220.080 228.042 0.965 1.003 -7.961
save.restore.p50_ms ms 12.198 10.368 1.176 1.001 1.830
save.restore.p95_ms ms 15.202 14.100 1.078 1.144 1.102
search.query.p50_ms ms 1.887 1.956 0.965 1.032 -0.069
search.query.p95_ms ms 4.209 4.314 0.976 0.997 -0.104
200 append total ms 946.856 912.665 1.037 0.964 34.191

100000 notes, native

metric unit b dev b/dev copy/dev control delta
cold.disk_written.p50 MB 1918.714 1918.757 1.000 1.000 -0.043
cold.disk_written.p95 MB 1918.714 1918.757 1.000 1.000 -0.043
cold.first_page.p50 ms 1608.933 1704.872 0.944 0.932 -95.939
cold.first_page.p95 ms 1608.933 1704.872 0.944 0.932 -95.939
cold.index.p50 s 15.116 15.157 0.997 0.991 -0.042
cold.index.p95 s 15.116 15.157 0.997 0.991 -0.042
cold.mem_peak.p50 MB 289.725 290.809 0.996 0.992 -1.084
cold.mem_peak.p95 MB 289.725 290.809 0.996 0.992 -1.084
cold.notes_per_s.p50 notes/s 6615.682 6597.640 1.003 1.009 18.042
cold.notes_per_s.p95 notes/s 6615.682 6597.640 1.003 1.009 18.042
cold.startup.p50 ms 13.577 14.569 0.932 0.336 -0.992
cold.startup.p95 ms 13.577 14.569 0.932 0.336 -0.992
home.first_page.p50 ms 3.359 3.219 1.044 0.965 0.140
home.first_page.p95 ms 4.034 4.641 0.869 1.146 -0.608
home.page.p50 ms 0.929 0.935 0.993 1.084 -0.007
home.page.p95 ms 1.326 1.500 0.884 1.616 -0.174
home.page_big.p50 ms 18.476 18.300 1.010 1.015 0.176
home.page_big.p95 ms 23.702 21.763 1.089 0.947 1.939
home.page_next.p50 ms 0.730 0.740 0.987 1.021 -0.009
home.page_next.p95 ms 1.073 1.059 1.014 1.045 0.015
home.page_tag.p50 ms 53.155 51.989 1.022 0.999 1.166
home.page_tag.p95 ms 79.178 56.293 1.407 0.983 22.886
home.page_title.p50 ms 0.885 0.807 1.096 1.031 0.077
home.page_title.p95 ms 1.235 1.387 0.890 1.633 -0.152
journal.catch_up.p50 ms 283.352 283.182 1.001 1.014 0.170
journal.catch_up.p95 ms 309.240 298.760 1.035 1.018 10.480
journal.entries.p50 count 100000.000 100000.000 1.000 1.000 0.000
journal.entries.p95 count 100000.000 100000.000 1.000 1.000 0.000
journal.page.p50 ms 2.499 2.488 1.004 1.002 0.011
journal.page.p95 ms 2.982 3.009 0.991 1.050 -0.027
mem.after_first_page.p50 MB 22.643 23.221 0.975 1.010 -0.578
mem.after_first_page.p95 MB 22.893 23.838 0.960 1.026 -0.945
mem.after_opens.p50 MB 92.984 96.738 0.961 1.022 -3.754
mem.after_opens.p95 MB 95.855 97.957 0.979 0.999 -2.102
mem.idle.p50 MB 19.525 19.439 1.004 0.992 0.086
mem.idle.p95 MB 19.664 21.068 0.933 1.057 -1.404
open.api_get.p50 ms 6.405 6.405 1.000 1.428 -0.001
open.api_get.p95 ms 10.692 10.166 1.052 1.690 0.526
open.long_note.p50 ms 65.632 64.655 1.015 1.463 0.977
open.long_note.p95 ms 75.889 72.601 1.045 1.644 3.288
open.note.p50 ms 0.781 0.751 1.040 1.030 0.030
open.note.p95 ms 3.649 3.406 1.071 1.016 0.243
shutdown.p50 ms 21.953 21.965 0.999 1.000 -0.012
shutdown.p95 ms 42.626 22.023 1.936 0.978 20.603
startup.healthz.p50 ms 5.066 5.006 1.012 1.006 0.060
startup.healthz.p95 ms 5.635 7.658 0.736 1.244 -2.023

failures

[]

option b main campaign results, 5 november, 15:23 ist. b does not qualify for adoption. head `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1`, dev `9377d711217532a44973edcf63c2af0b7f7969d8`. exact head binary sha256 `e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c`; dev binary `e7fce554632c7a35dd6fc424fd55f29a86377f04d12228141b23037b8176f5d5`. no cache drop. both shared perf locks were held together, perf-01 confirmed acquired before perf-02. measurements ran on perf-01. both holders were stopped after the campaign. 48 custom arms completed, 16 per size: three dev/b/dev/b cycles, then dev/dev-copy/dev/dev-copy. native websocket/journal harness completed 16 arms, each covering all three sizes, with three warm runs per arm and one cold run. no custom failure files and no native recorded failures. medians below are medians of arm quantiles, not pooled quantiles. control columns are the same-session dev-copy/dev ratio; do not subtract this ratio from b's results or use it to waive regressions. raw request samples and arm ranges will be attached. full-fill timing includes projection publication. the first-page metric is the first notes.list response after health readiness, including lazy Home open; the native harness also reports cold.first_page and warm home.first_page separately. startup-check timing is observed completion during early requests, with a 20 ms polling interval. RSS uses the child process only: 10 ms samples plus kernel VmHWM. steady fill is sampled two seconds after publication; startup steady follows the settled request campaign. the 720-second idle campaign is separate and still running. native mem.idle here uses --idle-secs 0 and is not the 720-second idle gate. | notes | b/dev fill peak maximum, mib | b/dev warm-check peak maximum, mib | largest paired b-minus-dev fill peak, mib | largest paired b-minus-dev check peak, mib | |---|---:|---:|---:|---:| | 1k | 47.344 / 46.984 | 26.664 / 26.535 | +1.266 | +0.980 | | 10k | 144.805 / 145.008 | 42.016 / 43.145 | +0.883 | +2.574 | | 100k | 298.324 / 296.160 | 126.188 / 129.840 | +6.305 | +6.348 | the tested single-Home paired peak excess is below 50 mib in every arm. this measures total process RSS differences, not isolated map allocation, and does not qualify concurrent first fills or the full aggregate envelope. internal b timings, six arms each: | notes | one projection publication median (range), ms | sort median, ms | ordered merge median, ms | |---|---:|---:|---:| | 1k | 51.5 (51–58) | 0.067 | 0.881 | | 10k | 93 (89–95) | 0.869 | 12.593 | | 100k | 579.5 (573–608) | 11.437 | 125.045 | current gate verdicts: 100k fill <=60 s passes its absolute budget; cold first-page <=100 ms fails; native open.note p95 <=15 ms passes its absolute budget. the requirement that every touched hot path be flat or better fails qualification: for example, settled 100k append p95 is 14.721 ms versus 12.107 ms (+21.6%; dev-copy control +10.9%), settled 1k create is 31.065 versus 22.856 ms (+35.9%; control +9.9%), and 10k native api-get p95 is 10.121 versus 7.477 ms (+35.4%; control -11.4%). noisy paths also cannot pass. startup-check and publication overhead are included and reported below. the inherited 704 mib configured aggregate cache allowance fails the unchanged 64 mib bound. idle, concurrent first fills, and the 100×100k/ten-active envelope remain unqualified pending the remaining measurements and feasibility check. no gate was loosened. functional final-head checks are still queued behind the existing dev-01 reservation. exact measurement commands, using the attached unchanged scripts: ```sh # holder command, first on perf-01; confirm ready before requesting perf-02 systemd-run --user --unit=tob-measure-hold --collect -p RuntimeMaxSec=10800 \ ~/bin/perf-lock bash -c 'date -u +%s > "$HOME/tob-lock-6c.ready"; sleep 7200' TOB_ROOT="$HOME/tob-b2" \ TOB_HEAD_SHA=3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 \ TOB_DEV_SHA=9377d711217532a44973edcf63c2af0b7f7969d8 \ python3 "$HOME/tob/measure.py" --sizes 1000,10000,100000 --cycles 3 TOB_ROOT="$HOME/tob-b2" bash "$HOME/tob/native.sh" # native.sh uses each arm's exact binary with: PERF_ONLY=list,query,journal,open GLIBC_TUNABLES=glibc.malloc.arena_max=2 \ "$B/calternal-perf-filtered" --bin "$B/calternal-$arm" --work "$work" \ --sizes 1k,10k,100k --runs 3 --cold-runs 1 --seed 1 --idle-secs 0 \ --json "$R/$label.json" --md "$R/$label.md" # stop on both hosts systemctl --user stop tob-measure-hold.service ``` all VM access used `timeout 60 netbird ssh claude@calternal-perf-01-backup01.vpn.kayg.org '<command>'` or the corresponding perf-02 address. the custom driver sets `CALTERNAL_NOTES_SAVE_MS=15` and `GLIBC_TUNABLES=glibc.malloc.arena_max=2`. script sha256 `ab2176240bb0f4894ccd9689aa803ea45832064d9cc59f386d1c5609795beaf5`; filtered native harness sha256 `352d448a4e7ef2c8099eb38ad02fd2fea2be93b6f7cba6bc83d29bf3cd7ce374`. full tables follow. RSS values labelled MB by the native harness are its original labels; custom process values are mib. every early/settled p50/p95 delta and native metric is retained, including regressions. medians across complete arms; control uses the same-session dev-copy arms. raw failures remain failures. ### 1000 notes, process | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | first_page_ms | ms | 307.816 | 302.432 | 1.018 | 0.951 | 5.384 | | first_fill_discovery_ms | ms | 359.362 | 353.950 | 1.015 | 0.957 | 5.412 | | first_fill_with_projection_ms | ms | 379.553 | 354.056 | 1.072 | 0.957 | 25.497 | | startup_ready_ms | ms | 21.227 | 21.297 | 0.997 | 0.992 | -0.070 | | startup_check_ms | ms | 22.175 | 24.416 | 0.908 | 1.466 | -2.241 | | fill.vmhwm_mib | MiB | 47.121 | 46.861 | 1.006 | 0.996 | 0.260 | | fill.steady_rss_mib | MiB | 30.781 | 39.582 | 0.778 | 1.099 | -8.801 | | startup_check_peak_rss_mib | MiB | 26.406 | 26.213 | 1.007 | 1.050 | 0.193 | | rss_at_check_complete_mib | MiB | 26.320 | 25.959 | 1.014 | 1.063 | 0.361 | | startup.vmhwm_mib | MiB | 50.068 | 48.969 | 1.022 | 1.002 | 1.100 | | startup.steady_rss_mib | MiB | 45.654 | 45.389 | 1.006 | 1.023 | 0.266 | | materialized_home_allocated_bytes | bytes | 53030912.000 | 48490496.000 | 1.094 | 1.000 | 4540416.000 | ### 1000 notes, early | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 7.991 | 7.911 | 1.010 | 0.991 | 0.080 | | list.big.p95_ms | ms | 8.754 | 8.972 | 0.976 | 0.973 | -0.218 | | list.next.p50_ms | ms | 0.884 | 0.872 | 1.014 | 1.092 | 0.012 | | list.next.p95_ms | ms | 0.966 | 0.940 | 1.027 | 1.125 | 0.026 | | list.page.p50_ms | ms | 1.034 | 1.038 | 0.997 | 1.022 | -0.003 | | list.page.p95_ms | ms | 1.236 | 1.259 | 0.982 | 1.015 | -0.023 | | list.tag.p50_ms | ms | 1.487 | 1.470 | 1.011 | 1.005 | 0.017 | | list.tag.p95_ms | ms | 1.698 | 1.761 | 0.964 | 0.867 | -0.063 | | list.title.p50_ms | ms | 0.793 | 0.796 | 0.996 | 1.023 | -0.003 | | list.title.p95_ms | ms | 0.957 | 0.961 | 0.996 | 0.941 | -0.004 | | read.api.p50_ms | ms | 4.933 | 4.874 | 1.012 | 0.992 | 0.058 | | read.api.p95_ms | ms | 5.877 | 5.719 | 1.028 | 1.022 | 0.159 | | save.append.p50_ms | ms | 5.537 | 5.518 | 1.004 | 1.009 | 0.020 | | save.append.p95_ms | ms | 15.262 | 15.060 | 1.013 | 1.139 | 0.202 | | save.create.p50_ms | ms | 21.916 | 16.803 | 1.304 | 1.020 | 5.113 | | save.create.p95_ms | ms | 37.108 | 22.203 | 1.671 | 0.950 | 14.906 | | save.delete.p50_ms | ms | 41.071 | 36.739 | 1.118 | 1.026 | 4.332 | | save.delete.p95_ms | ms | 46.245 | 42.007 | 1.101 | 0.943 | 4.238 | | save.rename.p50_ms | ms | 24.158 | 19.691 | 1.227 | 1.017 | 4.467 | | save.rename.p95_ms | ms | 28.985 | 22.921 | 1.265 | 0.863 | 6.064 | | save.restore.p50_ms | ms | 12.176 | 10.183 | 1.196 | 1.028 | 1.993 | | save.restore.p95_ms | ms | 14.241 | 11.928 | 1.194 | 1.115 | 2.313 | | search.query.p50_ms | ms | 0.597 | 0.443 | 1.350 | 0.908 | 0.155 | | search.query.p95_ms | ms | 9.752 | 8.250 | 1.182 | 1.250 | 1.502 | | 200 append total | ms | 1152.734 | 1149.311 | 1.003 | 1.035 | 3.423 | ### 1000 notes, settled | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 8.631 | 8.669 | 0.996 | 1.011 | -0.038 | | list.big.p95_ms | ms | 9.398 | 9.239 | 1.017 | 0.973 | 0.160 | | list.next.p50_ms | ms | 0.957 | 0.925 | 1.035 | 0.933 | 0.032 | | list.next.p95_ms | ms | 1.076 | 1.013 | 1.063 | 0.956 | 0.064 | | list.page.p50_ms | ms | 1.137 | 1.098 | 1.036 | 1.005 | 0.039 | | list.page.p95_ms | ms | 1.377 | 1.422 | 0.968 | 0.957 | -0.045 | | list.tag.p50_ms | ms | 1.574 | 1.573 | 1.001 | 0.976 | 0.001 | | list.tag.p95_ms | ms | 1.765 | 1.786 | 0.988 | 0.958 | -0.021 | | list.title.p50_ms | ms | 0.882 | 0.874 | 1.009 | 0.990 | 0.008 | | list.title.p95_ms | ms | 1.029 | 1.043 | 0.987 | 0.988 | -0.014 | | read.api.p50_ms | ms | 0.338 | 0.301 | 1.123 | 1.063 | 0.037 | | read.api.p95_ms | ms | 0.397 | 0.392 | 1.013 | 1.031 | 0.005 | | save.append.p50_ms | ms | 3.923 | 3.908 | 1.004 | 0.979 | 0.015 | | save.append.p95_ms | ms | 17.406 | 17.919 | 0.971 | 1.119 | -0.512 | | save.create.p50_ms | ms | 21.829 | 16.934 | 1.289 | 0.980 | 4.895 | | save.create.p95_ms | ms | 31.065 | 22.856 | 1.359 | 1.099 | 8.208 | | save.delete.p50_ms | ms | 41.154 | 36.797 | 1.118 | 0.990 | 4.357 | | save.delete.p95_ms | ms | 45.612 | 42.103 | 1.083 | 0.970 | 3.509 | | save.rename.p50_ms | ms | 24.239 | 19.950 | 1.215 | 0.990 | 4.290 | | save.rename.p95_ms | ms | 28.895 | 27.998 | 1.032 | 0.971 | 0.896 | | save.restore.p50_ms | ms | 12.215 | 10.242 | 1.193 | 0.975 | 1.973 | | save.restore.p95_ms | ms | 16.765 | 11.255 | 1.490 | 0.756 | 5.509 | | search.query.p50_ms | ms | 1.557 | 1.552 | 1.003 | 1.113 | 0.005 | | search.query.p95_ms | ms | 2.573 | 2.540 | 1.013 | 1.066 | 0.033 | | 200 append total | ms | 1056.900 | 1096.858 | 0.964 | 0.969 | -39.958 | ### 1000 notes, native | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | cold.disk_written.p50 | MB | 19.292 | 18.780 | 1.027 | 0.999 | 0.512 | | cold.disk_written.p95 | MB | 19.292 | 18.780 | 1.027 | 0.999 | 0.512 | | cold.first_page.p50 | ms | 361.492 | 380.538 | 0.950 | 1.027 | -19.046 | | cold.first_page.p95 | ms | 361.492 | 380.538 | 0.950 | 1.027 | -19.046 | | cold.index.p50 | s | 0.464 | 0.483 | 0.961 | 1.022 | -0.019 | | cold.index.p95 | s | 0.464 | 0.483 | 0.961 | 1.022 | -0.019 | | cold.mem_peak.p50 | MB | 46.510 | 46.592 | 0.998 | 1.001 | -0.082 | | cold.mem_peak.p95 | MB | 46.510 | 46.592 | 0.998 | 1.001 | -0.082 | | cold.notes_per_s.p50 | notes/s | 2156.430 | 2071.669 | 1.041 | 0.979 | 84.761 | | cold.notes_per_s.p95 | notes/s | 2156.430 | 2071.669 | 1.041 | 0.979 | 84.761 | | cold.startup.p50 | ms | 16.504 | 17.756 | 0.930 | 0.936 | -1.252 | | cold.startup.p95 | ms | 16.504 | 17.756 | 0.930 | 0.936 | -1.252 | | home.first_page.p50 | ms | 1.754 | 2.054 | 0.854 | 0.638 | -0.300 | | home.first_page.p95 | ms | 2.730 | 3.676 | 0.743 | 0.657 | -0.947 | | home.page.p50 | ms | 0.708 | 0.689 | 1.027 | 1.036 | 0.019 | | home.page.p95 | ms | 1.445 | 1.527 | 0.946 | 0.738 | -0.082 | | home.page_big.p50 | ms | 7.989 | 7.989 | 1.000 | 0.990 | -0.000 | | home.page_big.p95 | ms | 8.611 | 8.550 | 1.007 | 1.033 | 0.061 | | home.page_next.p50 | ms | 0.726 | 0.740 | 0.981 | 0.938 | -0.014 | | home.page_next.p95 | ms | 0.788 | 0.803 | 0.981 | 0.965 | -0.015 | | home.page_tag.p50 | ms | 1.224 | 1.250 | 0.979 | 0.986 | -0.026 | | home.page_tag.p95 | ms | 1.358 | 1.394 | 0.974 | 0.951 | -0.036 | | home.page_title.p50 | ms | 0.597 | 0.589 | 1.013 | 0.926 | 0.008 | | home.page_title.p95 | ms | 0.685 | 0.701 | 0.978 | 0.824 | -0.016 | | journal.catch_up.p50 | ms | 2.984 | 2.918 | 1.023 | 0.990 | 0.066 | | journal.catch_up.p95 | ms | 3.442 | 3.203 | 1.075 | 0.981 | 0.239 | | journal.entries.p50 | count | 1000.000 | 1000.000 | 1.000 | 1.000 | 0.000 | | journal.entries.p95 | count | 1000.000 | 1000.000 | 1.000 | 1.000 | 0.000 | | journal.page.p50 | ms | 2.727 | 2.663 | 1.024 | 0.989 | 0.064 | | journal.page.p95 | ms | 3.178 | 2.928 | 1.085 | 0.983 | 0.250 | | mem.after_first_page.p50 | MB | 21.967 | 21.842 | 1.006 | 0.989 | 0.125 | | mem.after_first_page.p95 | MB | 22.244 | 22.131 | 1.005 | 0.980 | 0.113 | | mem.after_opens.p50 | MB | 35.271 | 34.504 | 1.022 | 0.990 | 0.768 | | mem.after_opens.p95 | MB | 35.420 | 34.773 | 1.019 | 1.005 | 0.646 | | mem.idle.p50 | MB | 19.205 | 19.133 | 1.004 | 1.025 | 0.072 | | mem.idle.p95 | MB | 19.748 | 19.672 | 1.004 | 1.015 | 0.076 | | open.api_get.p50 | ms | 6.105 | 5.850 | 1.044 | 1.055 | 0.255 | | open.api_get.p95 | ms | 10.002 | 9.552 | 1.047 | 1.081 | 0.450 | | open.long_note.p50 | ms | 15.333 | 15.140 | 1.013 | 0.860 | 0.193 | | open.long_note.p95 | ms | 44.672 | 44.887 | 0.995 | 1.058 | -0.215 | | open.note.p50 | ms | 0.690 | 0.685 | 1.008 | 1.007 | 0.005 | | open.note.p95 | ms | 2.292 | 2.245 | 1.021 | 1.053 | 0.047 | | shutdown.p50 | ms | 42.948 | 42.678 | 1.006 | 0.999 | 0.271 | | shutdown.p95 | ms | 43.056 | 43.079 | 0.999 | 0.796 | -0.023 | | startup.healthz.p50 | ms | 4.949 | 5.227 | 0.947 | 1.118 | -0.279 | | startup.healthz.p95 | ms | 6.036 | 6.162 | 0.980 | 0.945 | -0.126 | ### 10000 notes, process | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | first_page_ms | ms | 229.571 | 226.882 | 1.012 | 0.985 | 2.689 | | first_fill_discovery_ms | ms | 1370.830 | 1316.425 | 1.041 | 1.002 | 54.405 | | first_fill_with_projection_ms | ms | 1439.256 | 1316.638 | 1.093 | 1.002 | 122.618 | | startup_ready_ms | ms | 21.314 | 21.205 | 1.005 | 1.076 | 0.108 | | startup_check_ms | ms | 126.710 | 120.300 | 1.053 | 0.940 | 6.410 | | fill.vmhwm_mib | MiB | 143.875 | 144.436 | 0.996 | 1.002 | -0.561 | | fill.steady_rss_mib | MiB | 56.686 | 137.666 | 0.412 | 0.989 | -80.980 | | startup_check_peak_rss_mib | MiB | 41.543 | 40.707 | 1.021 | 0.981 | 0.836 | | rss_at_check_complete_mib | MiB | 38.070 | 37.172 | 1.024 | 0.963 | 0.898 | | startup.vmhwm_mib | MiB | 77.129 | 76.867 | 1.003 | 0.995 | 0.262 | | startup.steady_rss_mib | MiB | 58.607 | 60.143 | 0.974 | 1.035 | -1.535 | | materialized_home_allocated_bytes | bytes | 238360576.000 | 230969344.000 | 1.032 | 1.000 | 7391232.000 | ### 10000 notes, early | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 16.566 | 17.257 | 0.960 | 0.999 | -0.691 | | list.big.p95_ms | ms | 24.514 | 22.000 | 1.114 | 1.070 | 2.514 | | list.next.p50_ms | ms | 0.830 | 0.868 | 0.956 | 1.025 | -0.038 | | list.next.p95_ms | ms | 0.963 | 0.974 | 0.989 | 0.948 | -0.011 | | list.page.p50_ms | ms | 1.245 | 1.324 | 0.940 | 0.983 | -0.079 | | list.page.p95_ms | ms | 2.004 | 2.040 | 0.982 | 0.978 | -0.036 | | list.tag.p50_ms | ms | 5.405 | 5.498 | 0.983 | 1.015 | -0.093 | | list.tag.p95_ms | ms | 6.665 | 6.811 | 0.979 | 1.047 | -0.146 | | list.title.p50_ms | ms | 0.851 | 0.874 | 0.973 | 1.010 | -0.023 | | list.title.p95_ms | ms | 1.025 | 1.148 | 0.892 | 0.923 | -0.124 | | read.api.p50_ms | ms | 4.842 | 4.844 | 0.999 | 0.983 | -0.003 | | read.api.p95_ms | ms | 6.928 | 5.197 | 1.333 | 1.303 | 1.731 | | save.append.p50_ms | ms | 5.418 | 5.402 | 1.003 | 0.992 | 0.016 | | save.append.p95_ms | ms | 15.837 | 16.796 | 0.943 | 1.051 | -0.959 | | save.create.p50_ms | ms | 27.137 | 22.169 | 1.224 | 1.000 | 4.969 | | save.create.p95_ms | ms | 42.271 | 32.025 | 1.320 | 1.106 | 10.247 | | save.delete.p50_ms | ms | 41.463 | 36.766 | 1.128 | 0.997 | 4.697 | | save.delete.p95_ms | ms | 52.459 | 49.102 | 1.068 | 0.993 | 3.357 | | save.rename.p50_ms | ms | 35.575 | 31.074 | 1.145 | 0.989 | 4.500 | | save.rename.p95_ms | ms | 40.064 | 35.735 | 1.121 | 0.942 | 4.329 | | save.restore.p50_ms | ms | 12.233 | 10.155 | 1.205 | 1.007 | 2.078 | | save.restore.p95_ms | ms | 17.627 | 14.683 | 1.201 | 1.248 | 2.944 | | search.query.p50_ms | ms | 0.408 | 0.398 | 1.025 | 1.036 | 0.010 | | search.query.p95_ms | ms | 2.192 | 0.778 | 2.819 | 1.639 | 1.414 | | 200 append total | ms | 1126.591 | 1127.146 | 1.000 | 1.012 | -0.555 | ### 10000 notes, settled | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 17.665 | 18.179 | 0.972 | 1.055 | -0.514 | | list.big.p95_ms | ms | 18.976 | 19.652 | 0.966 | 1.083 | -0.676 | | list.next.p50_ms | ms | 0.898 | 0.886 | 1.014 | 1.058 | 0.012 | | list.next.p95_ms | ms | 1.019 | 1.033 | 0.986 | 0.977 | -0.014 | | list.page.p50_ms | ms | 1.369 | 1.438 | 0.952 | 1.082 | -0.068 | | list.page.p95_ms | ms | 1.618 | 1.668 | 0.970 | 0.864 | -0.050 | | list.tag.p50_ms | ms | 5.477 | 5.624 | 0.974 | 1.053 | -0.147 | | list.tag.p95_ms | ms | 5.995 | 6.113 | 0.981 | 1.058 | -0.118 | | list.title.p50_ms | ms | 0.965 | 0.984 | 0.981 | 1.148 | -0.019 | | list.title.p95_ms | ms | 1.151 | 1.237 | 0.930 | 1.142 | -0.086 | | read.api.p50_ms | ms | 0.316 | 0.307 | 1.030 | 1.081 | 0.009 | | read.api.p95_ms | ms | 0.374 | 0.361 | 1.035 | 1.096 | 0.013 | | save.append.p50_ms | ms | 3.727 | 3.695 | 1.009 | 1.023 | 0.032 | | save.append.p95_ms | ms | 17.208 | 16.968 | 1.014 | 1.209 | 0.240 | | save.create.p50_ms | ms | 27.288 | 22.747 | 1.200 | 0.998 | 4.541 | | save.create.p95_ms | ms | 36.017 | 29.828 | 1.207 | 1.069 | 6.189 | | save.delete.p50_ms | ms | 40.874 | 37.052 | 1.103 | 1.006 | 3.822 | | save.delete.p95_ms | ms | 45.897 | 43.685 | 1.051 | 1.086 | 2.212 | | save.rename.p50_ms | ms | 35.772 | 31.890 | 1.122 | 0.989 | 3.882 | | save.rename.p95_ms | ms | 42.396 | 36.988 | 1.146 | 0.939 | 5.408 | | save.restore.p50_ms | ms | 12.082 | 10.312 | 1.172 | 1.009 | 1.770 | | save.restore.p95_ms | ms | 19.410 | 16.822 | 1.154 | 0.623 | 2.588 | | search.query.p50_ms | ms | 1.652 | 1.667 | 0.991 | 1.010 | -0.015 | | search.query.p95_ms | ms | 4.261 | 4.222 | 1.009 | 1.061 | 0.039 | | 200 append total | ms | 1011.121 | 985.155 | 1.026 | 1.024 | 25.965 | ### 10000 notes, native | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | cold.disk_written.p50 | MB | 150.112 | 150.163 | 1.000 | 1.004 | -0.051 | | cold.disk_written.p95 | MB | 150.112 | 150.163 | 1.000 | 1.004 | -0.051 | | cold.first_page.p50 | ms | 285.410 | 281.734 | 1.013 | 1.059 | 3.676 | | cold.first_page.p95 | ms | 285.410 | 281.734 | 1.013 | 1.059 | 3.676 | | cold.index.p50 | s | 1.414 | 1.411 | 1.002 | 1.047 | 0.003 | | cold.index.p95 | s | 1.414 | 1.411 | 1.002 | 1.047 | 0.003 | | cold.mem_peak.p50 | MB | 143.934 | 144.816 | 0.994 | 1.007 | -0.883 | | cold.mem_peak.p95 | MB | 143.934 | 144.816 | 0.994 | 1.007 | -0.883 | | cold.notes_per_s.p50 | notes/s | 7072.257 | 7086.895 | 0.998 | 0.954 | -14.638 | | cold.notes_per_s.p95 | notes/s | 7072.257 | 7086.895 | 0.998 | 0.954 | -14.638 | | cold.startup.p50 | ms | 17.289 | 15.641 | 1.105 | 1.001 | 1.647 | | cold.startup.p95 | ms | 17.289 | 15.641 | 1.105 | 1.001 | 1.647 | | home.first_page.p50 | ms | 3.085 | 2.658 | 1.161 | 1.409 | 0.427 | | home.first_page.p95 | ms | 3.731 | 5.050 | 0.739 | 1.128 | -1.319 | | home.page.p50 | ms | 0.721 | 0.774 | 0.931 | 1.058 | -0.053 | | home.page.p95 | ms | 1.891 | 2.460 | 0.768 | 0.700 | -0.570 | | home.page_big.p50 | ms | 16.457 | 16.815 | 0.979 | 1.010 | -0.358 | | home.page_big.p95 | ms | 17.270 | 18.427 | 0.937 | 0.952 | -1.157 | | home.page_next.p50 | ms | 0.735 | 0.752 | 0.977 | 1.029 | -0.017 | | home.page_next.p95 | ms | 0.816 | 0.873 | 0.935 | 1.007 | -0.057 | | home.page_tag.p50 | ms | 5.564 | 5.510 | 1.010 | 1.027 | 0.054 | | home.page_tag.p95 | ms | 8.202 | 7.594 | 1.080 | 0.968 | 0.609 | | home.page_title.p50 | ms | 0.686 | 0.686 | 0.999 | 1.095 | -0.000 | | home.page_title.p95 | ms | 0.876 | 0.911 | 0.962 | 1.198 | -0.035 | | journal.catch_up.p50 | ms | 28.180 | 28.815 | 0.978 | 1.016 | -0.635 | | journal.catch_up.p95 | ms | 33.134 | 30.544 | 1.085 | 1.043 | 2.590 | | journal.entries.p50 | count | 10000.000 | 10000.000 | 1.000 | 1.000 | 0.000 | | journal.entries.p95 | count | 10000.000 | 10000.000 | 1.000 | 1.000 | 0.000 | | journal.page.p50 | ms | 2.517 | 2.534 | 0.993 | 1.012 | -0.017 | | journal.page.p95 | ms | 2.798 | 3.191 | 0.877 | 1.083 | -0.394 | | mem.after_first_page.p50 | MB | 22.312 | 21.982 | 1.015 | 1.002 | 0.330 | | mem.after_first_page.p95 | MB | 22.559 | 22.715 | 0.993 | 1.032 | -0.156 | | mem.after_opens.p50 | MB | 43.145 | 41.672 | 1.035 | 1.023 | 1.473 | | mem.after_opens.p95 | MB | 43.543 | 42.828 | 1.017 | 0.999 | 0.715 | | mem.idle.p50 | MB | 19.102 | 19.195 | 0.995 | 1.003 | -0.094 | | mem.idle.p95 | MB | 19.408 | 20.305 | 0.956 | 1.017 | -0.896 | | open.api_get.p50 | ms | 4.801 | 4.850 | 0.990 | 0.863 | -0.049 | | open.api_get.p95 | ms | 10.121 | 7.477 | 1.354 | 0.886 | 2.644 | | open.long_note.p50 | ms | 17.680 | 18.941 | 0.933 | 1.671 | -1.262 | | open.long_note.p95 | ms | 46.764 | 46.046 | 1.016 | 1.041 | 0.718 | | open.note.p50 | ms | 0.763 | 0.738 | 1.033 | 0.993 | 0.024 | | open.note.p95 | ms | 4.181 | 4.085 | 1.023 | 0.968 | 0.095 | | shutdown.p50 | ms | 43.036 | 42.571 | 1.011 | 0.764 | 0.465 | | shutdown.p95 | ms | 43.171 | 43.091 | 1.002 | 1.005 | 0.081 | | startup.healthz.p50 | ms | 4.947 | 5.086 | 0.973 | 0.887 | -0.140 | | startup.healthz.p95 | ms | 5.213 | 8.492 | 0.614 | 1.377 | -3.279 | ### 100000 notes, process | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | first_page_ms | ms | 1620.156 | 1603.764 | 1.010 | 1.072 | 16.391 | | first_fill_discovery_ms | ms | 15107.703 | 15103.746 | 1.000 | 1.021 | 3.957 | | first_fill_with_projection_ms | ms | 15684.382 | 15103.999 | 1.038 | 1.021 | 580.383 | | startup_ready_ms | ms | 21.303 | 21.336 | 0.998 | 0.999 | -0.033 | | startup_check_ms | ms | 1249.453 | 1184.274 | 1.055 | 1.011 | 65.179 | | fill.vmhwm_mib | MiB | 290.348 | 292.877 | 0.991 | 0.982 | -2.529 | | fill.steady_rss_mib | MiB | 160.615 | 271.037 | 0.593 | 0.986 | -110.422 | | startup_check_peak_rss_mib | MiB | 125.277 | 125.520 | 0.998 | 1.005 | -0.242 | | rss_at_check_complete_mib | MiB | 93.348 | 96.477 | 0.968 | 0.967 | -3.129 | | startup.vmhwm_mib | MiB | 125.375 | 135.914 | 0.922 | 0.966 | -10.539 | | startup.steady_rss_mib | MiB | 114.705 | 126.773 | 0.905 | 0.981 | -12.068 | | materialized_home_allocated_bytes | bytes | 2457296896.000 | 2419812352.000 | 1.015 | 1.000 | 37484544.000 | ### 100000 notes, early | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 20.310 | 20.462 | 0.993 | 0.995 | -0.152 | | list.big.p95_ms | ms | 29.501 | 30.264 | 0.975 | 1.047 | -0.763 | | list.next.p50_ms | ms | 0.843 | 0.861 | 0.979 | 0.993 | -0.018 | | list.next.p95_ms | ms | 0.945 | 1.048 | 0.901 | 0.981 | -0.103 | | list.page.p50_ms | ms | 1.639 | 1.624 | 1.009 | 0.959 | 0.015 | | list.page.p95_ms | ms | 2.600 | 2.873 | 0.905 | 0.720 | -0.273 | | list.tag.p50_ms | ms | 53.551 | 52.274 | 1.024 | 1.008 | 1.277 | | list.tag.p95_ms | ms | 62.701 | 55.881 | 1.122 | 1.010 | 6.820 | | list.title.p50_ms | ms | 1.045 | 1.040 | 1.005 | 1.096 | 0.006 | | list.title.p95_ms | ms | 1.375 | 1.468 | 0.937 | 1.130 | -0.093 | | read.api.p50_ms | ms | 5.888 | 4.833 | 1.218 | 1.008 | 1.055 | | read.api.p95_ms | ms | 8.999 | 5.825 | 1.545 | 0.677 | 3.175 | | save.append.p50_ms | ms | 5.632 | 5.083 | 1.108 | 0.901 | 0.549 | | save.append.p95_ms | ms | 15.926 | 14.413 | 1.105 | 0.982 | 1.513 | | save.create.p50_ms | ms | 86.617 | 80.699 | 1.073 | 1.002 | 5.918 | | save.create.p95_ms | ms | 95.927 | 86.261 | 1.112 | 1.018 | 9.666 | | save.delete.p50_ms | ms | 46.956 | 36.925 | 1.272 | 0.987 | 10.031 | | save.delete.p95_ms | ms | 56.869 | 58.399 | 0.974 | 0.956 | -1.530 | | save.rename.p50_ms | ms | 164.966 | 159.962 | 1.031 | 1.000 | 5.004 | | save.rename.p95_ms | ms | 175.252 | 170.788 | 1.026 | 0.990 | 4.464 | | save.restore.p50_ms | ms | 14.166 | 10.336 | 1.371 | 0.980 | 3.830 | | save.restore.p95_ms | ms | 20.400 | 16.429 | 1.242 | 0.939 | 3.971 | | search.query.p50_ms | ms | 0.375 | 0.380 | 0.987 | 0.883 | -0.005 | | search.query.p95_ms | ms | 0.596 | 0.597 | 0.997 | 0.428 | -0.002 | | 200 append total | ms | 1247.307 | 1126.605 | 1.107 | 1.019 | 120.702 | ### 100000 notes, settled | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 22.273 | 20.997 | 1.061 | 0.961 | 1.276 | | list.big.p95_ms | ms | 40.953 | 38.741 | 1.057 | 0.986 | 2.212 | | list.next.p50_ms | ms | 0.847 | 0.849 | 0.998 | 0.948 | -0.001 | | list.next.p95_ms | ms | 0.972 | 0.968 | 1.005 | 0.851 | 0.004 | | list.page.p50_ms | ms | 1.640 | 1.531 | 1.071 | 0.999 | 0.109 | | list.page.p95_ms | ms | 5.038 | 6.081 | 0.828 | 0.987 | -1.043 | | list.tag.p50_ms | ms | 74.510 | 54.532 | 1.366 | 1.092 | 19.978 | | list.tag.p95_ms | ms | 213.362 | 211.662 | 1.008 | 1.041 | 1.701 | | list.title.p50_ms | ms | 1.074 | 1.081 | 0.994 | 0.977 | -0.007 | | list.title.p95_ms | ms | 4.211 | 3.575 | 1.178 | 1.211 | 0.636 | | read.api.p50_ms | ms | 0.334 | 0.317 | 1.055 | 0.942 | 0.017 | | read.api.p95_ms | ms | 0.417 | 0.405 | 1.031 | 0.967 | 0.013 | | save.append.p50_ms | ms | 3.726 | 3.594 | 1.037 | 0.971 | 0.132 | | save.append.p95_ms | ms | 14.721 | 12.107 | 1.216 | 1.109 | 2.614 | | save.create.p50_ms | ms | 85.000 | 82.158 | 1.035 | 1.011 | 2.841 | | save.create.p95_ms | ms | 92.096 | 90.358 | 1.019 | 1.016 | 1.739 | | save.delete.p50_ms | ms | 41.143 | 37.413 | 1.100 | 1.007 | 3.730 | | save.delete.p95_ms | ms | 52.808 | 45.949 | 1.149 | 0.946 | 6.859 | | save.rename.p50_ms | ms | 171.418 | 184.557 | 0.929 | 1.131 | -13.139 | | save.rename.p95_ms | ms | 220.080 | 228.042 | 0.965 | 1.003 | -7.961 | | save.restore.p50_ms | ms | 12.198 | 10.368 | 1.176 | 1.001 | 1.830 | | save.restore.p95_ms | ms | 15.202 | 14.100 | 1.078 | 1.144 | 1.102 | | search.query.p50_ms | ms | 1.887 | 1.956 | 0.965 | 1.032 | -0.069 | | search.query.p95_ms | ms | 4.209 | 4.314 | 0.976 | 0.997 | -0.104 | | 200 append total | ms | 946.856 | 912.665 | 1.037 | 0.964 | 34.191 | ### 100000 notes, native | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | cold.disk_written.p50 | MB | 1918.714 | 1918.757 | 1.000 | 1.000 | -0.043 | | cold.disk_written.p95 | MB | 1918.714 | 1918.757 | 1.000 | 1.000 | -0.043 | | cold.first_page.p50 | ms | 1608.933 | 1704.872 | 0.944 | 0.932 | -95.939 | | cold.first_page.p95 | ms | 1608.933 | 1704.872 | 0.944 | 0.932 | -95.939 | | cold.index.p50 | s | 15.116 | 15.157 | 0.997 | 0.991 | -0.042 | | cold.index.p95 | s | 15.116 | 15.157 | 0.997 | 0.991 | -0.042 | | cold.mem_peak.p50 | MB | 289.725 | 290.809 | 0.996 | 0.992 | -1.084 | | cold.mem_peak.p95 | MB | 289.725 | 290.809 | 0.996 | 0.992 | -1.084 | | cold.notes_per_s.p50 | notes/s | 6615.682 | 6597.640 | 1.003 | 1.009 | 18.042 | | cold.notes_per_s.p95 | notes/s | 6615.682 | 6597.640 | 1.003 | 1.009 | 18.042 | | cold.startup.p50 | ms | 13.577 | 14.569 | 0.932 | 0.336 | -0.992 | | cold.startup.p95 | ms | 13.577 | 14.569 | 0.932 | 0.336 | -0.992 | | home.first_page.p50 | ms | 3.359 | 3.219 | 1.044 | 0.965 | 0.140 | | home.first_page.p95 | ms | 4.034 | 4.641 | 0.869 | 1.146 | -0.608 | | home.page.p50 | ms | 0.929 | 0.935 | 0.993 | 1.084 | -0.007 | | home.page.p95 | ms | 1.326 | 1.500 | 0.884 | 1.616 | -0.174 | | home.page_big.p50 | ms | 18.476 | 18.300 | 1.010 | 1.015 | 0.176 | | home.page_big.p95 | ms | 23.702 | 21.763 | 1.089 | 0.947 | 1.939 | | home.page_next.p50 | ms | 0.730 | 0.740 | 0.987 | 1.021 | -0.009 | | home.page_next.p95 | ms | 1.073 | 1.059 | 1.014 | 1.045 | 0.015 | | home.page_tag.p50 | ms | 53.155 | 51.989 | 1.022 | 0.999 | 1.166 | | home.page_tag.p95 | ms | 79.178 | 56.293 | 1.407 | 0.983 | 22.886 | | home.page_title.p50 | ms | 0.885 | 0.807 | 1.096 | 1.031 | 0.077 | | home.page_title.p95 | ms | 1.235 | 1.387 | 0.890 | 1.633 | -0.152 | | journal.catch_up.p50 | ms | 283.352 | 283.182 | 1.001 | 1.014 | 0.170 | | journal.catch_up.p95 | ms | 309.240 | 298.760 | 1.035 | 1.018 | 10.480 | | journal.entries.p50 | count | 100000.000 | 100000.000 | 1.000 | 1.000 | 0.000 | | journal.entries.p95 | count | 100000.000 | 100000.000 | 1.000 | 1.000 | 0.000 | | journal.page.p50 | ms | 2.499 | 2.488 | 1.004 | 1.002 | 0.011 | | journal.page.p95 | ms | 2.982 | 3.009 | 0.991 | 1.050 | -0.027 | | mem.after_first_page.p50 | MB | 22.643 | 23.221 | 0.975 | 1.010 | -0.578 | | mem.after_first_page.p95 | MB | 22.893 | 23.838 | 0.960 | 1.026 | -0.945 | | mem.after_opens.p50 | MB | 92.984 | 96.738 | 0.961 | 1.022 | -3.754 | | mem.after_opens.p95 | MB | 95.855 | 97.957 | 0.979 | 0.999 | -2.102 | | mem.idle.p50 | MB | 19.525 | 19.439 | 1.004 | 0.992 | 0.086 | | mem.idle.p95 | MB | 19.664 | 21.068 | 0.933 | 1.057 | -1.404 | | open.api_get.p50 | ms | 6.405 | 6.405 | 1.000 | 1.428 | -0.001 | | open.api_get.p95 | ms | 10.692 | 10.166 | 1.052 | 1.690 | 0.526 | | open.long_note.p50 | ms | 65.632 | 64.655 | 1.015 | 1.463 | 0.977 | | open.long_note.p95 | ms | 75.889 | 72.601 | 1.045 | 1.644 | 3.288 | | open.note.p50 | ms | 0.781 | 0.751 | 1.040 | 1.030 | 0.030 | | open.note.p95 | ms | 3.649 | 3.406 | 1.071 | 1.016 | 0.243 | | shutdown.p50 | ms | 21.953 | 21.965 | 0.999 | 1.000 | -0.012 | | shutdown.p95 | ms | 42.626 | 22.023 | 1.936 | 0.978 | 20.603 | | startup.healthz.p50 | ms | 5.066 | 5.006 | 1.012 | 1.006 | 0.060 | | startup.healthz.p95 | ms | 5.635 | 7.658 | 0.736 | 1.244 | -2.023 | ### failures []
Author
Owner

main-campaign raw artifact: tob-main-3f9ce0fd.tar.gz.

contains all 48 custom arm results, 96 raw RSS series, 16 native JSON reports, numeric-only publication/classification diagnostics, full comparison tables, exact external scripts, and a file hash manifest. server logs and setup output are excluded. results are attached here only and are not committed. the separate 720-second idle results and final validation/cleanup report will follow.

main-campaign raw artifact: [tob-main-3f9ce0fd.tar.gz](https://git.kayg.org/attachments/945c9f07-3987-44c3-bfdb-e3edb5e5b4a5). contains all 48 custom arm results, 96 raw RSS series, 16 native JSON reports, numeric-only publication/classification diagnostics, full comparison tables, exact external scripts, and a file hash manifest. server logs and setup output are excluded. results are attached here only and are not committed. the separate 720-second idle results and final validation/cleanup report will follow.
Author
Owner

correction to the gate label in comment 79742: perf/budgets.json applies the 100 ms first-page budget specifically to home.first_page@100000, an indexed-home reopen. b's native median arm p95 is 4.034 ms versus dev's 4.641 ms, so that named absolute gate passes. the fresh, never-indexed Home response is a separate cold.first_page metric: the custom run measured 1,620.156 ms versus 1,603.764 ms, and the native cold values are retained in the full table. the existing JSON does not assign that cold metric the same 100 ms budget. the final gate table will keep these definitions explicit instead of presenting the cold value as a failure of the named warm gate.

this corrects a measurement label; no limit changes. b still fails qualification under the unchanged requirement that every hot path be flat or better, and its configured 704 mib aggregate cache allowance still fails the 64 mib bound. the 720-second idle campaign remains running. API append timings are API save measurements, not the editor's websocket sync.save_ack; no websocket-save budget pass is claimed from them.

correction to the gate label in comment 79742: `perf/budgets.json` applies the 100 ms first-page budget specifically to `home.first_page@100000`, an indexed-home reopen. b's native median arm p95 is 4.034 ms versus dev's 4.641 ms, so that named absolute gate passes. the fresh, never-indexed Home response is a separate `cold.first_page` metric: the custom run measured 1,620.156 ms versus 1,603.764 ms, and the native cold values are retained in the full table. the existing JSON does not assign that cold metric the same 100 ms budget. the final gate table will keep these definitions explicit instead of presenting the cold value as a failure of the named warm gate. this corrects a measurement label; no limit changes. b still fails qualification under the unchanged requirement that every hot path be flat or better, and its configured 704 mib aggregate cache allowance still fails the 64 mib bound. the 720-second idle campaign remains running. API append timings are API save measurements, not the editor's websocket `sync.save_ack`; no websocket-save budget pass is claimed from them.
Author
Owner

measured capacity checkpoint, 5 november, 15:52 ist:

first 720-second idle pair: dev 91.01953125 mib, b 74.13671875 mib. these are individual arms, not the final campaign medians; the remaining six arms, including the idle dev-copy control, are still running under both ordered locks.

allocated bytes after the measured server stopped, immediately before deleting that arm's Home:

component b bytes dev bytes
independent user data 2,448,478,208 2,415,104,000
note files 678,334,464 678,350,848
notes metadata/history/identity directory 901,021,696 867,618,816
notes/meta.db 846,499,840 846,487,552
search 854,188,032 854,188,032

100 times b's observed per-user allocation is 244,847,820,800 bytes, about 228.03 gib. the entire perf-01 filesystem is only 105,467,994,112 bytes, about 98.23 gib. it therefore cannot materialize 100 equivalent independent Homes, even before leaving the mandatory 15 gib free. this is a feasibility calculation from measured on-disk allocation, not a measured 100-Home runtime result. final clean free bytes and all per-arm footprints will be reported after cleanup.

the full 100×100k / ten simultaneously active envelope will not be seeded unsafely. it remains unrun and fails qualification here; a single 1m-note Home, sparse files, or ten independent server processes will not be presented as a substitute. the 1m active envelope and concurrent first fills are also unqualified. no cache or latency gate changes.

measured capacity checkpoint, 5 november, 15:52 ist: first 720-second idle pair: dev 91.01953125 mib, b 74.13671875 mib. these are individual arms, not the final campaign medians; the remaining six arms, including the idle dev-copy control, are still running under both ordered locks. allocated bytes after the measured server stopped, immediately before deleting that arm's Home: | component | b bytes | dev bytes | |---|---:|---:| | independent user data | 2,448,478,208 | 2,415,104,000 | | note files | 678,334,464 | 678,350,848 | | notes metadata/history/identity directory | 901,021,696 | 867,618,816 | | notes/meta.db | 846,499,840 | 846,487,552 | | search | 854,188,032 | 854,188,032 | 100 times b's observed per-user allocation is 244,847,820,800 bytes, about 228.03 gib. the entire perf-01 filesystem is only 105,467,994,112 bytes, about 98.23 gib. it therefore cannot materialize 100 equivalent independent Homes, even before leaving the mandatory 15 gib free. this is a feasibility calculation from measured on-disk allocation, not a measured 100-Home runtime result. final clean free bytes and all per-arm footprints will be reported after cleanup. the full 100×100k / ten simultaneously active envelope will not be seeded unsafely. it remains unrun and fails qualification here; a single 1m-note Home, sparse files, or ten independent server processes will not be presented as a substitute. the 1m active envelope and concurrent first fills are also unqualified. no cache or latency gate changes.
Author
Owner

final-head functional validation passed, 5 november, 16:00 ist:

3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 passed notes all-target compilation, the admission regression, six option-b tests, formatting, strict workspace clippy, the full workspace test command, and release build. notes' full run: 591 passed, 0 failed, 7 ignored. the whole set-e validation job exited 0; rustfmt left zero diff bytes and the VM worktree is clean. the owned 13 gib shared target was removed after all owned dev jobs settled.

exact commands on dev-01, through /nix/var/nix/profiles/default/bin/nix develop -c bash -c "~/bin/slot bash ~/tob-check-body.sh", with CARGO_TARGET_DIR="$HOME/Developer/Worktrees/tiering-option-b/target":

cargo fmt --all
cargo check -j4 -p calternal-notes --all-targets --locked
cargo test -j4 -p calternal-notes warm_discovery_surfaces_refused_identity_admission --locked -- --nocapture
cargo test -j4 -p calternal-notes option_b_tests --locked -- --nocapture
cargo fmt --all --check
cargo clippy -j4 --workspace --all-targets --locked -- -D warnings
cargo test -j4 --workspace --locked --no-fail-fast -- --test-threads=2
cargo build --release -j4 --locked -p calternal -p calternal-fixtures

the measured artifact is still the immutable e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c, built at this exact head by release5. the later validation worktree produced 93f3b99fc162c5f73fb15fc537db8f405dffcaea5c47a36b3b2853767583f562; that binary has not replaced the measured one or been mixed into any result group. validation records will accompany the final artifact.

memory-allowance clarification: the original recommendation in #792 comment 78352 described the temporary map as “about +50 MB at 100k, as dev does all the time.” comparison with dev therefore does not isolate the map: both use it during first fill. the measured paired b-minus-dev peak excess is <=6.348 mib, but that alone cannot certify the original map-memory claim.

notes b fill peak minus two-second steady rss, median / maximum, mib dev same gap, median / maximum, mib
1k 16.355 / 17.418 7.037 / 12.848
10k 87.299 / 89.777 6.076 / 9.965
100k 133.426 / 199.746 24.654 / 29.613

these are medians of within-arm gaps, so subtracting the separately reported median peak and median steady values need not give the same median gap. they measure the whole process, including scan/search/projection/allocator effects. they are not an isolated allocation count for the map. under a 50 mib total peak-above-post-fill-steady interpretation, the 100k result exceeds the allowance in every arm (smallest observed gap 56.629 mib). the narrower claim that the map alone costs at most 50 mib remains unverified. the final verdict will not mark the original 50 mib transient claim passed on the strength of the paired dev comparison.

mount check: perf-01 has the measured ext4 root (98.23 gib total) and a rotational xfs /srv/homes volume (100 gib total, about 26 gib free), with no mounted /mnt/b/hdd-ext4 or /mnt/z4-nvme. neither can accommodate the measured 228.03 gib independent-user footprint for 100 Homes with the required reserve. the scale qualification remains unrun, not a pass.

no source changes, adoption, or merge. six idle arms remain to finish.

final-head functional validation passed, 5 november, 16:00 ist: `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1` passed notes all-target compilation, the admission regression, six option-b tests, formatting, strict workspace clippy, the full workspace test command, and release build. notes' full run: 591 passed, 0 failed, 7 ignored. the whole set-e validation job exited 0; rustfmt left zero diff bytes and the VM worktree is clean. the owned 13 gib shared target was removed after all owned dev jobs settled. exact commands on dev-01, through `/nix/var/nix/profiles/default/bin/nix develop -c bash -c "~/bin/slot bash ~/tob-check-body.sh"`, with `CARGO_TARGET_DIR="$HOME/Developer/Worktrees/tiering-option-b/target"`: ```sh cargo fmt --all cargo check -j4 -p calternal-notes --all-targets --locked cargo test -j4 -p calternal-notes warm_discovery_surfaces_refused_identity_admission --locked -- --nocapture cargo test -j4 -p calternal-notes option_b_tests --locked -- --nocapture cargo fmt --all --check cargo clippy -j4 --workspace --all-targets --locked -- -D warnings cargo test -j4 --workspace --locked --no-fail-fast -- --test-threads=2 cargo build --release -j4 --locked -p calternal -p calternal-fixtures ``` the measured artifact is still the immutable `e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c`, built at this exact head by release5. the later validation worktree produced `93f3b99fc162c5f73fb15fc537db8f405dffcaea5c47a36b3b2853767583f562`; that binary has not replaced the measured one or been mixed into any result group. validation records will accompany the final artifact. memory-allowance clarification: the original recommendation in #792 comment 78352 described the temporary map as “about +50 MB at 100k, as dev does all the time.” comparison with dev therefore does not isolate the map: both use it during first fill. the measured paired b-minus-dev peak excess is <=6.348 mib, but that alone cannot certify the original map-memory claim. | notes | b fill peak minus two-second steady rss, median / maximum, mib | dev same gap, median / maximum, mib | |---|---:|---:| | 1k | 16.355 / 17.418 | 7.037 / 12.848 | | 10k | 87.299 / 89.777 | 6.076 / 9.965 | | 100k | 133.426 / 199.746 | 24.654 / 29.613 | these are medians of within-arm gaps, so subtracting the separately reported median peak and median steady values need not give the same median gap. they measure the whole process, including scan/search/projection/allocator effects. they are not an isolated allocation count for the map. under a 50 mib total peak-above-post-fill-steady interpretation, the 100k result exceeds the allowance in every arm (smallest observed gap 56.629 mib). the narrower claim that the map alone costs at most 50 mib remains unverified. the final verdict will not mark the original 50 mib transient claim passed on the strength of the paired dev comparison. mount check: perf-01 has the measured ext4 root (98.23 gib total) and a rotational xfs `/srv/homes` volume (100 gib total, about 26 gib free), with no mounted `/mnt/b/hdd-ext4` or `/mnt/z4-nvme`. neither can accommodate the measured 228.03 gib independent-user footprint for 100 Homes with the required reserve. the scale qualification remains unrun, not a pass. no source changes, adoption, or merge. six idle arms remain to finish.
Author
Owner

final option b report, 5 november, 17:16 ist. b fails qualification. no adoption or merge.

head 3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1; dev baseline 9377d711217532a44973edcf63c2af0b7f7969d8. measured head binary sha256 e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c. the later validation binary was not mixed into these results. the branch is clean and pushed; the PR stays a draft.

completed: 48 custom main arms, 16 native arms (each covering 1k/10k/100k), and eight 100k idle arms. no recorded custom/native failures. main groups are six b, six dev, two dev-copy and two control-dev per size. idle groups are two of each. both locks were acquired in order, perf-01 confirmed ready before requesting perf-02, and held together in each session. all measurements ran on perf-01. both holders are stopped.

main campaign medians, b / dev. fill includes publication. fill steady is specifically the snapshot two seconds after publication, not a claim that all background search work is quiescent. check peak includes kernel VmHWM up to observed warm-check completion; startup steady follows the settled request campaign. rss is whole-process mib.

notes fill b / dev, s warm check b / dev, ms fill peak b / dev, mib fill steady b / dev, mib check peak b / dev, mib check complete b / dev, mib startup steady b / dev, mib
1000 0.380 / 0.354 22.175 / 24.416 47.121 / 46.861 30.781 / 39.582 26.406 / 26.213 26.320 / 25.959 45.654 / 45.389
10000 1.439 / 1.317 126.710 / 120.300 143.875 / 144.436 56.686 / 137.666 41.543 / 40.707 38.070 / 37.172 58.607 / 60.143
100000 15.684 / 15.104 1249.453 / 1184.274 290.348 / 292.877 160.615 / 271.037 125.277 / 125.520 93.348 / 96.477 114.705 / 126.773

maximum paired b peak excess over dev: first fill +6.305 mib; warm check +6.348 mib. maximum absolute b fill peak was 298.324 mib; maximum warm-check peak 126.188 mib in the main campaign. the supplemental idle campaign did not exceed these paired excesses.

selected p95 results below show why the no-regression gate fails. all early/settled p50/p95 and native metrics remain in the main table; no noisy control was used to waive a regression.

notes measurement b ms dev ms b delta dev-copy control delta
1000 settled create 31.065 22.856 +35.9% +9.9%
10000 native API read 10.121 7.477 +35.4% -11.4%
100000 native tagged page 79.178 56.293 +40.7% -1.7%
100000 settled API append 14.721 12.107 +21.6% +10.9%
100000 settled search 4.209 4.314 -2.4% -0.3%

720-second idle campaign, separate from the main groups:

group endpoint median, mib endpoint range, mib
b 77.029 74.137–79.922
dev 90.725 90.430–91.020
dev-copy 93.361 92.961–93.762
control-dev 91.527 90.586–92.469

b/dev idle ratio 0.849045, -15.1%; control ratio 1.020038, +2.0%. final-minute p95 and maximum equal the endpoint in every arm; the raw series and window summaries are attached. the 100 mb idle budget passes for the tested single Home. this does not qualify 100 Homes or concurrent fills.

gate verdict evidence / limit
final-head functional checks pass notes 591 passed, 0 failed, 7 ignored; full workspace job exit 0; fmt, strict clippy and release passed
every touched hot path flat or better than dev fail tagged-page p95 +40.7% with control -1.7%; other read/save regressions above; all deltas retained
100k fill including publication <=60 s pass at measured protocol main b median 15.684 s; every arm below 60 s
home.first_page@100000 p95 <=100 ms pass at measured protocol native b maximum arm p95 6.917 ms; cold.first_page is a separate metric, per correction 79765
later tag page p95 <=50 ms fail native b median arm p95 79.178 ms, range 75.867–81.284 ms
open.note p95 <=15 ms pass at measured protocol largest b arm p95 across sizes 7.035 ms
API read <=50 ms / long note <=250 ms pass at measured protocol largest b arm p95 12.178 / 97.100 ms
100k idle rss <=100 mb pass for tested single Home largest b endpoint and final-minute maximum 79.922 mib, about 83.80 decimal mb
global identity cache <=64 mib fail inherited configured allowance 704 mib across 128 leases, not measured consumption
original about-50-mib temporary-map claim fail qualification / unverified both b and dev hold the first-fill map, so <=6.348 mib paired excess cannot isolate its allocation
100×100k, ten active; 1m active; concurrent first fills fail qualification / unrun full materialized envelope cannot fit safely; no substitute workload or concurrency cap was invented

for the 50 mib comparison, the total process fill peak minus its two-second post-fill rss had a within-arm median gap of 133.426 mib, maximum 199.746 mib, at 100k (minimum 56.629 mib). this exceeds 50 mib if the allowance means total peak above that post-fill snapshot. these gaps include scan/search/projection/allocator effects and are not isolated map allocation. the specific map-memory claim therefore is not marked passed. detailed gap table and exact validation commands: comment 79781.

both stopped b idle Homes used exactly 2,448,478,208 allocated bytes per user: note files 678,334,464; notes metadata/history/identity directory 901,021,696 (including meta.db 846,499,840); search 854,188,032. 100 equivalent independent users require 244,847,820,800 bytes, 228.03 gib, calculated from those measured per-user allocations. this is a capacity feasibility calculation, not a measured 100-Home runtime result. root clean free bytes after cleanup: 79,446,827,008; reserving 15 gib leaves 63,340,699,648. the separate rotational xfs volume has only 27,760,361,472 bytes free. neither fits the envelope; even both entire filesystems together are smaller than the measured required user allocation. no sparse files, single 1m Home, or ten independent processes were substituted.

exact campaign commands, with scripts attached (VM access exclusively timeout 60 netbird ssh <exact-host> <command>):

export TOB_HEAD_SHA=3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1
export TOB_DEV_SHA=9377d711217532a44973edcf63c2af0b7f7969d8
TOB_ROOT="$HOME/tob-b2" python3 "$HOME/tob/measure.py" --sizes 1000,10000,100000 --cycles 3
TOB_ROOT="$HOME/tob-b2" bash "$HOME/tob/native.sh"
TOB_ROOT="$HOME/tob-idle" TOB_IDLE_SECS=720 python3 "$HOME/tob/idle.py" --sizes 100000 --cycles 1

fresh idle holders used the following on perf-01, waited for its ready marker, then the same command on perf-02; the idle matrix unit had RuntimeMaxSec=6900. main holders and native command expansion are in comment 79742.

systemd-run --user --unit=tob-idle-hold --collect -p RuntimeMaxSec=10800 \
  ~/bin/perf-lock bash -c 'date -u +%s > "$HOME/tob-lock-idle.ready"; sleep 7200'
# after each campaign, on both hosts:
systemctl --user stop tob-idle-hold.service

no page-cache drop. Home and state were colocated on the ext4 SSD root, matching this lane's A comparison protocol; these are not split HDD/SSD production qualifications. GLIBC_TUNABLES=glibc.malloc.arena_max=2; custom API saves used CALTERNAL_NOTES_SAVE_MS=15 for both binaries. API append timing is not the editor's websocket sync.save_ack; no websocket-save budget pass is claimed. full scale, concurrent fill and split-storage qualifications remain unrun.

cleanup verified: no owned jobs running on dev-01/perf-01/perf-02; both lock holders stopped; all owned seeded work directories and native work directories gone; all four owned dev worktree target directories gone; copied dev/perf binaries removed. small JSON/MD reports and scripts retained. no main checkout was written. branch remains clean, draft, open and unmerged.

full supplemental idle comparisons follow; do not pool their two-arm medians with the six-arm main groups.

medians across complete arms; control uses the same-session dev-copy arms. raw failures remain failures.

100000 notes, process

metric unit b dev b/dev copy/dev control delta
first_page_ms ms 1623.455 1598.420 1.016 0.966 25.035
first_fill_discovery_ms ms 15199.274 14919.133 1.019 0.982 280.141
first_fill_with_projection_ms ms 15755.491 14919.390 1.056 0.982 836.101
startup_ready_ms ms 22.864 21.296 1.074 0.999 1.568
startup_check_ms ms 1222.083 1142.221 1.070 1.035 79.863
fill.vmhwm_mib MiB 287.072 287.760 0.998 0.991 -0.688
fill.steady_rss_mib MiB 135.439 259.867 0.521 1.003 -124.428
startup_check_peak_rss_mib MiB 126.891 127.689 0.994 0.966 -0.799
rss_at_check_complete_mib MiB 98.748 95.662 1.032 0.995 3.086
startup.vmhwm_mib MiB 127.414 130.771 0.974 0.996 -3.357
startup.steady_rss_mib MiB 115.793 108.146 1.071 1.192 7.646
idle_rss_mib MiB 77.029 90.725 0.849 1.020 -13.695
materialized_home_allocated_bytes bytes 2457108480.000 2419632128.000 1.015 1.000 37476352.000

100000 notes, early

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 19.704 20.125 0.979 1.086 -0.421
list.big.p95_ms ms 28.260 23.354 1.210 0.921 4.905
list.next.p50_ms ms 0.840 0.873 0.963 1.055 -0.033
list.next.p95_ms ms 0.967 0.978 0.990 1.198 -0.010
list.page.p50_ms ms 1.495 1.692 0.883 0.931 -0.198
list.page.p95_ms ms 2.236 2.491 0.897 0.814 -0.255
list.tag.p50_ms ms 53.755 52.738 1.019 0.983 1.017
list.tag.p95_ms ms 60.893 57.065 1.067 1.001 3.828
list.title.p50_ms ms 0.997 1.004 0.992 0.900 -0.008
list.title.p95_ms ms 1.453 1.559 0.932 1.056 -0.106
read.api.p50_ms ms 4.955 5.039 0.983 1.030 -0.085
read.api.p95_ms ms 7.145 6.579 1.086 0.902 0.565
save.append.p50_ms ms 5.299 4.691 1.130 1.027 0.608
save.append.p95_ms ms 12.831 13.486 0.951 0.677 -0.655
save.create.p50_ms ms 84.430 80.465 1.049 0.997 3.965
save.create.p95_ms ms 91.361 89.522 1.021 0.996 1.839
save.delete.p50_ms ms 42.060 37.117 1.133 1.007 4.944
save.delete.p95_ms ms 47.655 42.466 1.122 0.994 5.189
save.rename.p50_ms ms 162.023 159.104 1.018 0.993 2.918
save.rename.p95_ms ms 169.459 168.721 1.004 0.979 0.738
save.restore.p50_ms ms 12.314 10.237 1.203 1.015 2.077
save.restore.p95_ms ms 22.655 12.671 1.788 1.470 9.983
search.query.p50_ms ms 0.382 0.386 0.992 0.957 -0.003
search.query.p95_ms ms 0.592 0.660 0.898 0.941 -0.068
200 append total ms 1073.795 1098.975 0.977 0.989 -25.179

100000 notes, settled

metric unit b dev b/dev copy/dev control delta
list.big.p50_ms ms 23.589 20.390 1.157 1.041 3.199
list.big.p95_ms ms 39.896 52.480 0.760 0.901 -12.584
list.next.p50_ms ms 0.865 0.845 1.024 0.953 0.020
list.next.p95_ms ms 0.997 0.933 1.069 0.867 0.064
list.page.p50_ms ms 1.676 1.508 1.112 1.044 0.168
list.page.p95_ms ms 4.565 6.045 0.755 0.999 -1.480
list.tag.p50_ms ms 121.840 53.331 2.285 1.049 68.509
list.tag.p95_ms ms 226.961 222.708 1.019 1.002 4.253
list.title.p50_ms ms 1.127 1.005 1.121 1.034 0.122
list.title.p95_ms ms 3.740 3.912 0.956 1.301 -0.173
read.api.p50_ms ms 0.376 0.338 1.112 1.061 0.038
read.api.p95_ms ms 0.483 0.433 1.117 1.141 0.051
save.append.p50_ms ms 3.665 3.631 1.009 0.989 0.034
save.append.p95_ms ms 7.853 10.841 0.724 0.684 -2.987
save.create.p50_ms ms 83.918 82.518 1.017 1.004 1.400
save.create.p95_ms ms 97.800 89.915 1.088 1.062 7.884
save.delete.p50_ms ms 40.039 37.488 1.068 1.007 2.551
save.delete.p95_ms ms 44.408 46.391 0.957 0.938 -1.982
save.rename.p50_ms ms 169.169 183.914 0.920 1.016 -14.746
save.rename.p95_ms ms 221.974 227.778 0.975 1.012 -5.804
save.restore.p50_ms ms 12.067 10.369 1.164 1.003 1.698
save.restore.p95_ms ms 13.743 12.242 1.123 1.011 1.501
search.query.p50_ms ms 1.867 1.949 0.958 0.947 -0.083
search.query.p95_ms ms 4.099 4.333 0.946 0.941 -0.235
200 append total ms 876.606 905.006 0.969 0.956 -28.400

failures

[]

raw artifacts:

server logs/setup output are excluded. all measurements and reports live in these PR comments/attachments, never in committed files.

final option b report, 5 november, 17:16 ist. **b fails qualification. no adoption or merge.** head `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1`; dev baseline `9377d711217532a44973edcf63c2af0b7f7969d8`. measured head binary sha256 `e2d4f96133289356c4770c7fff07746c0921f27db3d4200984482d7f6f12db8c`. the later validation binary was not mixed into these results. the branch is clean and pushed; the PR stays a draft. completed: 48 custom main arms, 16 native arms (each covering 1k/10k/100k), and eight 100k idle arms. no recorded custom/native failures. main groups are six b, six dev, two dev-copy and two control-dev per size. idle groups are two of each. both locks were acquired in order, perf-01 confirmed ready before requesting perf-02, and held together in each session. all measurements ran on perf-01. both holders are stopped. main campaign medians, b / dev. fill includes publication. fill steady is specifically the snapshot two seconds after publication, not a claim that all background search work is quiescent. check peak includes kernel VmHWM up to observed warm-check completion; startup steady follows the settled request campaign. rss is whole-process mib. | notes | fill b / dev, s | warm check b / dev, ms | fill peak b / dev, mib | fill steady b / dev, mib | check peak b / dev, mib | check complete b / dev, mib | startup steady b / dev, mib | |---|---:|---:|---:|---:|---:|---:|---:| | 1000 | 0.380 / 0.354 | 22.175 / 24.416 | 47.121 / 46.861 | 30.781 / 39.582 | 26.406 / 26.213 | 26.320 / 25.959 | 45.654 / 45.389 | | 10000 | 1.439 / 1.317 | 126.710 / 120.300 | 143.875 / 144.436 | 56.686 / 137.666 | 41.543 / 40.707 | 38.070 / 37.172 | 58.607 / 60.143 | | 100000 | 15.684 / 15.104 | 1249.453 / 1184.274 | 290.348 / 292.877 | 160.615 / 271.037 | 125.277 / 125.520 | 93.348 / 96.477 | 114.705 / 126.773 | maximum paired b peak excess over dev: first fill +6.305 mib; warm check +6.348 mib. maximum absolute b fill peak was 298.324 mib; maximum warm-check peak 126.188 mib in the main campaign. the supplemental idle campaign did not exceed these paired excesses. selected p95 results below show why the no-regression gate fails. all early/settled p50/p95 and native metrics remain in [the main table](https://git.kayg.org/kayg/calternal/pulls/953#issuecomment-79742); no noisy control was used to waive a regression. | notes | measurement | b ms | dev ms | b delta | dev-copy control delta | |---|---|---:|---:|---:|---:| | 1000 | settled create | 31.065 | 22.856 | +35.9% | +9.9% | | 10000 | native API read | 10.121 | 7.477 | +35.4% | -11.4% | | 100000 | native tagged page | 79.178 | 56.293 | +40.7% | -1.7% | | 100000 | settled API append | 14.721 | 12.107 | +21.6% | +10.9% | | 100000 | settled search | 4.209 | 4.314 | -2.4% | -0.3% | 720-second idle campaign, separate from the main groups: | group | endpoint median, mib | endpoint range, mib | |---|---:|---:| | b | 77.029 | 74.137–79.922 | | dev | 90.725 | 90.430–91.020 | | dev-copy | 93.361 | 92.961–93.762 | | control-dev | 91.527 | 90.586–92.469 | b/dev idle ratio 0.849045, -15.1%; control ratio 1.020038, +2.0%. final-minute p95 and maximum equal the endpoint in every arm; the raw series and window summaries are attached. the 100 mb idle budget passes for the tested single Home. this does not qualify 100 Homes or concurrent fills. | gate | verdict | evidence / limit | |---|---|---| | final-head functional checks | pass | notes 591 passed, 0 failed, 7 ignored; full workspace job exit 0; fmt, strict clippy and release passed | | every touched hot path flat or better than dev | fail | tagged-page p95 +40.7% with control -1.7%; other read/save regressions above; all deltas retained | | 100k fill including publication <=60 s | pass at measured protocol | main b median 15.684 s; every arm below 60 s | | home.first_page@100000 p95 <=100 ms | pass at measured protocol | native b maximum arm p95 6.917 ms; cold.first_page is a separate metric, per correction 79765 | | later tag page p95 <=50 ms | fail | native b median arm p95 79.178 ms, range 75.867–81.284 ms | | open.note p95 <=15 ms | pass at measured protocol | largest b arm p95 across sizes 7.035 ms | | API read <=50 ms / long note <=250 ms | pass at measured protocol | largest b arm p95 12.178 / 97.100 ms | | 100k idle rss <=100 mb | pass for tested single Home | largest b endpoint and final-minute maximum 79.922 mib, about 83.80 decimal mb | | global identity cache <=64 mib | fail | inherited configured allowance 704 mib across 128 leases, not measured consumption | | original about-50-mib temporary-map claim | fail qualification / unverified | both b and dev hold the first-fill map, so <=6.348 mib paired excess cannot isolate its allocation | | 100×100k, ten active; 1m active; concurrent first fills | fail qualification / unrun | full materialized envelope cannot fit safely; no substitute workload or concurrency cap was invented | for the 50 mib comparison, the total process fill peak minus its two-second post-fill rss had a within-arm median gap of **133.426 mib**, maximum **199.746 mib**, at 100k (minimum 56.629 mib). this exceeds 50 mib if the allowance means total peak above that post-fill snapshot. these gaps include scan/search/projection/allocator effects and are not isolated map allocation. the specific map-memory claim therefore is not marked passed. detailed gap table and exact validation commands: [comment 79781](https://git.kayg.org/kayg/calternal/pulls/953#issuecomment-79781). both stopped b idle Homes used exactly **2,448,478,208 allocated bytes per user**: note files 678,334,464; notes metadata/history/identity directory 901,021,696 (including meta.db 846,499,840); search 854,188,032. 100 equivalent independent users require **244,847,820,800 bytes, 228.03 gib**, calculated from those measured per-user allocations. this is a capacity feasibility calculation, not a measured 100-Home runtime result. root clean free bytes after cleanup: **79,446,827,008**; reserving 15 gib leaves **63,340,699,648**. the separate rotational xfs volume has only **27,760,361,472** bytes free. neither fits the envelope; even both entire filesystems together are smaller than the measured required user allocation. no sparse files, single 1m Home, or ten independent processes were substituted. exact campaign commands, with scripts attached (VM access exclusively `timeout 60 netbird ssh <exact-host> <command>`): ```sh export TOB_HEAD_SHA=3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 export TOB_DEV_SHA=9377d711217532a44973edcf63c2af0b7f7969d8 TOB_ROOT="$HOME/tob-b2" python3 "$HOME/tob/measure.py" --sizes 1000,10000,100000 --cycles 3 TOB_ROOT="$HOME/tob-b2" bash "$HOME/tob/native.sh" TOB_ROOT="$HOME/tob-idle" TOB_IDLE_SECS=720 python3 "$HOME/tob/idle.py" --sizes 100000 --cycles 1 ``` fresh idle holders used the following on perf-01, waited for its ready marker, then the same command on perf-02; the idle matrix unit had RuntimeMaxSec=6900. main holders and native command expansion are in comment 79742. ```sh systemd-run --user --unit=tob-idle-hold --collect -p RuntimeMaxSec=10800 \ ~/bin/perf-lock bash -c 'date -u +%s > "$HOME/tob-lock-idle.ready"; sleep 7200' # after each campaign, on both hosts: systemctl --user stop tob-idle-hold.service ``` no page-cache drop. Home and state were colocated on the ext4 SSD root, matching this lane's A comparison protocol; these are not split HDD/SSD production qualifications. `GLIBC_TUNABLES=glibc.malloc.arena_max=2`; custom API saves used `CALTERNAL_NOTES_SAVE_MS=15` for both binaries. API append timing is not the editor's websocket sync.save_ack; no websocket-save budget pass is claimed. full scale, concurrent fill and split-storage qualifications remain unrun. cleanup verified: no owned jobs running on dev-01/perf-01/perf-02; both lock holders stopped; all owned seeded work directories and native work directories gone; all four owned dev worktree target directories gone; copied dev/perf binaries removed. small JSON/MD reports and scripts retained. no main checkout was written. branch remains clean, draft, open and unmerged. full supplemental idle comparisons follow; do not pool their two-arm medians with the six-arm main groups. medians across complete arms; control uses the same-session dev-copy arms. raw failures remain failures. ### 100000 notes, process | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | first_page_ms | ms | 1623.455 | 1598.420 | 1.016 | 0.966 | 25.035 | | first_fill_discovery_ms | ms | 15199.274 | 14919.133 | 1.019 | 0.982 | 280.141 | | first_fill_with_projection_ms | ms | 15755.491 | 14919.390 | 1.056 | 0.982 | 836.101 | | startup_ready_ms | ms | 22.864 | 21.296 | 1.074 | 0.999 | 1.568 | | startup_check_ms | ms | 1222.083 | 1142.221 | 1.070 | 1.035 | 79.863 | | fill.vmhwm_mib | MiB | 287.072 | 287.760 | 0.998 | 0.991 | -0.688 | | fill.steady_rss_mib | MiB | 135.439 | 259.867 | 0.521 | 1.003 | -124.428 | | startup_check_peak_rss_mib | MiB | 126.891 | 127.689 | 0.994 | 0.966 | -0.799 | | rss_at_check_complete_mib | MiB | 98.748 | 95.662 | 1.032 | 0.995 | 3.086 | | startup.vmhwm_mib | MiB | 127.414 | 130.771 | 0.974 | 0.996 | -3.357 | | startup.steady_rss_mib | MiB | 115.793 | 108.146 | 1.071 | 1.192 | 7.646 | | idle_rss_mib | MiB | 77.029 | 90.725 | 0.849 | 1.020 | -13.695 | | materialized_home_allocated_bytes | bytes | 2457108480.000 | 2419632128.000 | 1.015 | 1.000 | 37476352.000 | ### 100000 notes, early | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 19.704 | 20.125 | 0.979 | 1.086 | -0.421 | | list.big.p95_ms | ms | 28.260 | 23.354 | 1.210 | 0.921 | 4.905 | | list.next.p50_ms | ms | 0.840 | 0.873 | 0.963 | 1.055 | -0.033 | | list.next.p95_ms | ms | 0.967 | 0.978 | 0.990 | 1.198 | -0.010 | | list.page.p50_ms | ms | 1.495 | 1.692 | 0.883 | 0.931 | -0.198 | | list.page.p95_ms | ms | 2.236 | 2.491 | 0.897 | 0.814 | -0.255 | | list.tag.p50_ms | ms | 53.755 | 52.738 | 1.019 | 0.983 | 1.017 | | list.tag.p95_ms | ms | 60.893 | 57.065 | 1.067 | 1.001 | 3.828 | | list.title.p50_ms | ms | 0.997 | 1.004 | 0.992 | 0.900 | -0.008 | | list.title.p95_ms | ms | 1.453 | 1.559 | 0.932 | 1.056 | -0.106 | | read.api.p50_ms | ms | 4.955 | 5.039 | 0.983 | 1.030 | -0.085 | | read.api.p95_ms | ms | 7.145 | 6.579 | 1.086 | 0.902 | 0.565 | | save.append.p50_ms | ms | 5.299 | 4.691 | 1.130 | 1.027 | 0.608 | | save.append.p95_ms | ms | 12.831 | 13.486 | 0.951 | 0.677 | -0.655 | | save.create.p50_ms | ms | 84.430 | 80.465 | 1.049 | 0.997 | 3.965 | | save.create.p95_ms | ms | 91.361 | 89.522 | 1.021 | 0.996 | 1.839 | | save.delete.p50_ms | ms | 42.060 | 37.117 | 1.133 | 1.007 | 4.944 | | save.delete.p95_ms | ms | 47.655 | 42.466 | 1.122 | 0.994 | 5.189 | | save.rename.p50_ms | ms | 162.023 | 159.104 | 1.018 | 0.993 | 2.918 | | save.rename.p95_ms | ms | 169.459 | 168.721 | 1.004 | 0.979 | 0.738 | | save.restore.p50_ms | ms | 12.314 | 10.237 | 1.203 | 1.015 | 2.077 | | save.restore.p95_ms | ms | 22.655 | 12.671 | 1.788 | 1.470 | 9.983 | | search.query.p50_ms | ms | 0.382 | 0.386 | 0.992 | 0.957 | -0.003 | | search.query.p95_ms | ms | 0.592 | 0.660 | 0.898 | 0.941 | -0.068 | | 200 append total | ms | 1073.795 | 1098.975 | 0.977 | 0.989 | -25.179 | ### 100000 notes, settled | metric | unit | b | dev | b/dev | copy/dev control | delta | |---|---|---:|---:|---:|---:|---:| | list.big.p50_ms | ms | 23.589 | 20.390 | 1.157 | 1.041 | 3.199 | | list.big.p95_ms | ms | 39.896 | 52.480 | 0.760 | 0.901 | -12.584 | | list.next.p50_ms | ms | 0.865 | 0.845 | 1.024 | 0.953 | 0.020 | | list.next.p95_ms | ms | 0.997 | 0.933 | 1.069 | 0.867 | 0.064 | | list.page.p50_ms | ms | 1.676 | 1.508 | 1.112 | 1.044 | 0.168 | | list.page.p95_ms | ms | 4.565 | 6.045 | 0.755 | 0.999 | -1.480 | | list.tag.p50_ms | ms | 121.840 | 53.331 | 2.285 | 1.049 | 68.509 | | list.tag.p95_ms | ms | 226.961 | 222.708 | 1.019 | 1.002 | 4.253 | | list.title.p50_ms | ms | 1.127 | 1.005 | 1.121 | 1.034 | 0.122 | | list.title.p95_ms | ms | 3.740 | 3.912 | 0.956 | 1.301 | -0.173 | | read.api.p50_ms | ms | 0.376 | 0.338 | 1.112 | 1.061 | 0.038 | | read.api.p95_ms | ms | 0.483 | 0.433 | 1.117 | 1.141 | 0.051 | | save.append.p50_ms | ms | 3.665 | 3.631 | 1.009 | 0.989 | 0.034 | | save.append.p95_ms | ms | 7.853 | 10.841 | 0.724 | 0.684 | -2.987 | | save.create.p50_ms | ms | 83.918 | 82.518 | 1.017 | 1.004 | 1.400 | | save.create.p95_ms | ms | 97.800 | 89.915 | 1.088 | 1.062 | 7.884 | | save.delete.p50_ms | ms | 40.039 | 37.488 | 1.068 | 1.007 | 2.551 | | save.delete.p95_ms | ms | 44.408 | 46.391 | 0.957 | 0.938 | -1.982 | | save.rename.p50_ms | ms | 169.169 | 183.914 | 0.920 | 1.016 | -14.746 | | save.rename.p95_ms | ms | 221.974 | 227.778 | 0.975 | 1.012 | -5.804 | | save.restore.p50_ms | ms | 12.067 | 10.369 | 1.164 | 1.003 | 1.698 | | save.restore.p95_ms | ms | 13.743 | 12.242 | 1.123 | 1.011 | 1.501 | | search.query.p50_ms | ms | 1.867 | 1.949 | 0.958 | 0.947 | -0.083 | | search.query.p95_ms | ms | 4.099 | 4.333 | 0.946 | 0.941 | -0.235 | | 200 append total | ms | 876.606 | 905.006 | 0.969 | 0.956 | -28.400 | ### failures [] raw artifacts: - [main campaign: 48 custom arms, 96 RSS series, 16 native reports, numeric diagnostics, scripts and manifest](https://git.kayg.org/attachments/945c9f07-3987-44c3-bfdb-e3edb5e5b4a5) - [final idle campaign: eight arms, 16 RSS series, eight capacity records, final-minute windows, validation, cleanup, scripts and manifest](https://git.kayg.org/attachments/8753b893-61c4-4981-a1b2-08365e1c4b77) server logs/setup output are excluded. all measurements and reports live in these PR comments/attachments, never in committed files.
Author
Owner

Orchestrator: option B is rejected. It saves memory (100k settled −10 %, idle −15 %), but reads (+35 %), appends (+22 %) and the tagged page (+41 %, 79 ms against the 50 ms gate) are slower than dev, and no perf regression may merge. A has failed too, so under the rethink rule I'm not patching B any further. A design-only lane is profiling why B is slower and writing docs/plans/tiering-v3.md, a simpler design that has to keep every hot path at or below dev. This PR stays a draft for reference until v3 decides what to keep or delete.

Orchestrator: **option B is rejected.** It saves memory (100k settled −10 %, idle −15 %), but reads (+35 %), appends (+22 %) and the tagged page (+41 %, 79 ms against the 50 ms gate) are slower than dev, and no perf regression may merge. A has failed too, so under the rethink rule I'm not patching B any further. A design-only lane is profiling *why* B is slower and writing `docs/plans/tiering-v3.md`, a simpler design that has to keep every hot path at or below dev. This PR stays a draft for reference until v3 decides what to keep or delete.
Author
Owner

Housekeeping #1009 status: audited head 3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1 against dev cd7f84432feb. git cherry origin/dev <head> reports 31 unmatched commits and 0 equivalent patches. Separate stable patch-id indexing and key-file checks do not establish full landing. Absent from dev: crates/notes/src/index/first.rs, crates/notes/src/index/option_b_tests.rs, crates/notes/src/index/paged.rs. Left unchanged as WIP, per kayg’s instruction; no rebase, close, tests, or merge. The #1009 audit records the unmatched commit list.

Housekeeping #1009 status: audited head `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1` against dev `cd7f84432feb`. `git cherry origin/dev <head>` reports 31 unmatched commits and 0 equivalent patches. Separate stable patch-id indexing and key-file checks do not establish full landing. Absent from dev: `crates/notes/src/index/first.rs`, `crates/notes/src/index/option_b_tests.rs`, `crates/notes/src/index/paged.rs`. Left unchanged as WIP, per kayg’s instruction; no rebase, close, tests, or merge. The #1009 audit records the unmatched commit list.
Author
Owner

Closing: option B was rejected on measured regressions (see the orchestrator comment above); the tiering design now lives in docs/plans/tiering-v3.md and the open slice PRs #970 / #1008. Head 3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1; reopen to revive the measurements. (Housekeeping 2026-11-09 night)

Closing: option B was rejected on measured regressions (see the orchestrator comment above); the tiering design now lives in `docs/plans/tiering-v3.md` and the open slice PRs #970 / #1008. Head `3f9ce0fd6acbbcdcc5100668ebf2b2a50b6c1cb1`; reopen to revive the measurements. (Housekeeping 2026-11-09 night)
kayg closed this pull request 2026-11-09 18:46:30 +00:00
Some checks failed
CI / web (pull_request) Has been cancelled
Markdown extraction contract / markdown-native-contract (pull_request) Has been cancelled
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
Markdown extraction contract / markdown-editor-contract (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!953
No description provided.