Notes: scrolling and opening a large Note are slow (5k fling p95 250 ms, 20k 725 ms) #1481

Open
opened 2026-10-08 20:30:03 +00:00 by kayg · 23 comments
Owner

Problem

Scrolling and opening a large Note are slow. Measured on the perf VM (2 interleaved pairs, origin/dev d395b6e25 vs job/bignote-1349 0743d5a9a; evidence on #1349):

Blocks Revision Cold open p95 Warm open p95 Scroll-frame p95
5000 dev 4056 ms 2464 ms 242 ms
5000 bignote 4245 ms 2024 ms 250 ms
20000 dev 7093 ms 5211 ms 533 ms
20000 bignote 5387 ms 4140 ms 725 ms

Mac Chrome (real GPU, one trial, 5k): cold open p95 8.8 s, fling scroll-frame p95 383 ms.

5k fling trace (Chrome): native intersection computation 3617 ms total; style-tree update 1268 ms; layout 1026 ms; Floating UI getCssDimensions 1456 ms; caretPositionFromPoint in BlockHoverActions 555 ms plus the drag-handle caret lookup 152 ms. Full-document JS still runs in TipTap code-block-lowlight (findChildren/nodesBetween) and the Yjs binding traversal.

Expected

Per DESIGN §59: a fling in a 5k-block Note keeps frames under budget (scroll-frame p95 ≤ 50 ms) and a warm open shows content within the open budget; work per frame does not grow with Note size. No hover/positioning geometry reads run during a scroll; IntersectionObservers are bounded to visible blocks.

Scope

Builds on job/bignote-1349 (typing fixes). Measure interleaved vs dev on the perf VM and on Mac Chrome. Keep collaboration (Yjs) safe: no change that drops or reorders updates.

## Problem Scrolling and opening a large Note are slow. Measured on the perf VM (2 interleaved pairs, origin/dev d395b6e25 vs job/bignote-1349 0743d5a9a; evidence on #1349): | Blocks | Revision | Cold open p95 | Warm open p95 | Scroll-frame p95 | | ---: | --- | ---: | ---: | ---: | | 5000 | dev | 4056 ms | 2464 ms | 242 ms | | 5000 | bignote | 4245 ms | 2024 ms | 250 ms | | 20000 | dev | 7093 ms | 5211 ms | 533 ms | | 20000 | bignote | 5387 ms | 4140 ms | 725 ms | Mac Chrome (real GPU, one trial, 5k): cold open p95 8.8 s, fling scroll-frame p95 383 ms. 5k fling trace (Chrome): native intersection computation 3617 ms total; style-tree update 1268 ms; layout 1026 ms; Floating UI getCssDimensions 1456 ms; caretPositionFromPoint in BlockHoverActions 555 ms plus the drag-handle caret lookup 152 ms. Full-document JS still runs in TipTap code-block-lowlight (findChildren/nodesBetween) and the Yjs binding traversal. ## Expected Per DESIGN §59: a fling in a 5k-block Note keeps frames under budget (scroll-frame p95 ≤ 50 ms) and a warm open shows content within the open budget; work per frame does not grow with Note size. No hover/positioning geometry reads run during a scroll; IntersectionObservers are bounded to visible blocks. ## Scope Builds on job/bignote-1349 (typing fixes). Measure interleaved vs dev on the perf VM and on Mac Chrome. Keep collaboration (Yjs) safe: no change that drops or reorders updates.
Author
Owner

Started #1481 on job/bigscroll-1481, based on job/bignote-1349 at 0743d5a9ad8b2567719e001d063c7a4e2decf7e6. I read the issue, the #1349 final report and the binding notes/editor and performance decisions. I am locating the scroll-time observers and hover geometry paths before making a focused, tested change. No API or Rust changes are planned yet.

Started #1481 on `job/bigscroll-1481`, based on `job/bignote-1349` at `0743d5a9ad8b2567719e001d063c7a4e2decf7e6`. I read the issue, the #1349 final report and the binding notes/editor and performance decisions. I am locating the scroll-time observers and hover geometry paths before making a focused, tested change. No API or Rust changes are planned yet.
Author
Owner

Finding from the #1481 5k fling trace and source inspection: the trace attributes 1,455.66 ms to Floating UI getCssDimensions, 555.43 ms to caretPositionFromPoint in BlockHoverActions and 151.61 ms to the drag-handle caret lookup. BlockHoverActions.svelte called scheduleReposition() for each captured scroll event; that path reads block/card rectangles and resolves line coordinates. The #1349 drag-handle guard dropped only same-coordinate passive mousemoves, so changed coordinates still reached TipTap's RAF hit test and Floating UI when the resolved block changed. I have now deferred these passive paths until 140 ms after the last scroll, and I am running focused regression tests for scroll-then-hover and the latest pointer target.

Finding from the #1481 5k fling trace and source inspection: the trace attributes 1,455.66 ms to Floating UI `getCssDimensions`, 555.43 ms to `caretPositionFromPoint` in BlockHoverActions and 151.61 ms to the drag-handle caret lookup. `BlockHoverActions.svelte` called `scheduleReposition()` for each captured scroll event; that path reads block/card rectangles and resolves line coordinates. The #1349 drag-handle guard dropped only same-coordinate passive mousemoves, so changed coordinates still reached TipTap's RAF hit test and Floating UI when the resolved block changed. I have now deferred these passive paths until 140 ms after the last scroll, and I am running focused regression tests for scroll-then-hover and the latest pointer target.
Author
Owner

Observer inventory for #1481: CanvasPreview.svelte and DrawingBlock.svelte each created their own IntersectionObserver, so a Note with N embedded Canvases allocated N observers. NoteContents.svelte already uses one observer for all outline headings. NoteCardsLayer.svelte uses one ResizeObserver for the editor containers, not one per block; it has no scroll listener. I replaced the per-embed observers with one shared observer, bounded to a 300 px vertical viewport window, and added tests for sharing, target cleanup and the no-IntersectionObserver fallback. Browser-managed content-visibility: auto remains in the Note CSS pending the controlled scroll trace; its impact needs measurement before changing the document layout model.

Observer inventory for #1481: `CanvasPreview.svelte` and `DrawingBlock.svelte` each created their own IntersectionObserver, so a Note with N embedded Canvases allocated N observers. `NoteContents.svelte` already uses one observer for all outline headings. `NoteCardsLayer.svelte` uses one ResizeObserver for the editor containers, not one per block; it has no scroll listener. I replaced the per-embed observers with one shared observer, bounded to a 300 px vertical viewport window, and added tests for sharing, target cleanup and the no-IntersectionObserver fallback. Browser-managed `content-visibility: auto` remains in the Note CSS pending the controlled scroll trace; its impact needs measurement before changing the document layout model.
Author
Owner

Implementation decisions:

  • Keep the existing 140 ms hover settle. During scrolling, passive pointer moves only cache coordinates; toolbar geometry resumes after the quiet period. An active drag and keyboard handle actions remain immediate.
  • Use one shared IntersectionObserver for Note Canvas previews and Drawing blocks, with a 300 px viewport margin. This matches the existing Drawing block lead-in and releases the observer when its last target leaves the tree.
  • Keep cold/warm open and fling latency samples untraced. Collect separate Chrome traces for source attribution so instrumentation does not inflate the reported percentiles.

These changes preserve the current Note content and Yjs update path. A focused scroll-then-hover test and the shared observer tests pass; full merged-branch measurements are in progress.

Implementation decisions: - Keep the existing 140 ms hover settle. During scrolling, passive pointer moves only cache coordinates; toolbar geometry resumes after the quiet period. An active drag and keyboard handle actions remain immediate. - Use one shared IntersectionObserver for Note Canvas previews and Drawing blocks, with a 300 px viewport margin. This matches the existing Drawing block lead-in and releases the observer when its last target leaves the tree. - Keep cold/warm open and fling latency samples untraced. Collect separate Chrome traces for source attribution so instrumentation does not inflate the reported percentiles. These changes preserve the current Note content and Yjs update path. A focused scroll-then-hover test and the shared observer tests pass; full merged-branch measurements are in progress.
Author
Owner

The merged production build passed the large Note visual/risk probe on Chromium with the platform set to MacIntel/macOS. It captured 24 screenshots across 390/820/1440 px and light/dark themes. The new mid-scroll hover state waited 160 ms after scroll and verified the real Block hover toolbar before capture. The run also confirmed the 5k Note reaches its measured bottom with 0 px input drift and 0 px clamp, and produced a 2,794,678-byte print PDF that contains Block 5000. The probe reported no app page errors. I will attach the screenshots and the raw run log with the final report.

The merged production build passed the large Note visual/risk probe on Chromium with the platform set to MacIntel/macOS. It captured 24 screenshots across 390/820/1440 px and light/dark themes. The new mid-scroll hover state waited 160 ms after scroll and verified the real Block hover toolbar before capture. The run also confirmed the 5k Note reaches its measured bottom with 0 px input drift and 0 px clamp, and produced a 2,794,678-byte print PDF that contains Block 5000. The probe reported no app page errors. I will attach the screenshots and the raw run log with the final report.
Author
Owner

Preliminary perf evidence from the first alternating pair on the locked perf VM (1440×900, headless Chromium; samples were untraced): 5k scroll-frame p95 was 349.9 ms on 0743d5a9a and 283.3 ms on this branch; 20k was 833.3 ms on both. Middle typing p95 was 138.5 ms vs 189.0 ms at 5k and 176.5 ms vs 180.3 ms at 20k. The 5k cold/warm open medians were 1528.7/1344.2 ms vs 1874.1/1789.9 ms. One pair is not enough to decide the deltas. The 50 ms scroll target is not met in this pair; I am checking five alternating pairs before drawing conclusions.

Preliminary perf evidence from the first alternating pair on the locked perf VM (1440×900, headless Chromium; samples were untraced): 5k scroll-frame p95 was 349.9 ms on 0743d5a9a and 283.3 ms on this branch; 20k was 833.3 ms on both. Middle typing p95 was 138.5 ms vs 189.0 ms at 5k and 176.5 ms vs 180.3 ms at 20k. The 5k cold/warm open medians were 1528.7/1344.2 ms vs 1874.1/1789.9 ms. One pair is not enough to decide the deltas. The 50 ms scroll target is not met in this pair; I am checking five alternating pairs before drawing conclusions.
Author
Owner

The second alternating pair completed on the perf VM. Its untraced p95 values were 250.1 ms vs 300.0 ms at 5k and 716.7 ms vs 833.4 ms at 20k (candidate vs 0743d5a9a). Middle-typing p95 was 103.1 ms vs 114.9 ms at 5k, but 234.9 ms vs 167.3 ms at 20k. Scroll improved in both pairs so far, remains above 50 ms, and 20k typing needs the remaining paired samples before I decide whether there is a regression.

The second alternating pair completed on the perf VM. Its untraced p95 values were 250.1 ms vs 300.0 ms at 5k and 716.7 ms vs 833.4 ms at 20k (candidate vs 0743d5a9a). Middle-typing p95 was 103.1 ms vs 114.9 ms at 5k, but 234.9 ms vs 167.3 ms at 20k. Scroll improved in both pairs so far, remains above 50 ms, and 20k typing needs the remaining paired samples before I decide whether there is a regression.
Author
Owner

The third alternating pair showed 5k scroll p95 283.3 ms vs 300.0 ms and 20k 850.0 ms vs 849.9 ms (branch vs 0743d5a9a). Middle typing p95 at 20k was 274.3 ms vs 174.6 ms; pair 2 had the same direction (234.9 ms vs 167.3 ms). Source review found the 140 ms settle timer synthesizes a mousemove at cached coordinates even without new pointer motion, which can trigger Floating UI and caret geometry during typing. I am changing this to resume hover only on a real pointer move after the quiet period. These first three pairs are exploratory; I will repeat the comparisons against the final implementation.

The third alternating pair showed 5k scroll p95 283.3 ms vs 300.0 ms and 20k 850.0 ms vs 849.9 ms (branch vs 0743d5a9a). Middle typing p95 at 20k was 274.3 ms vs 174.6 ms; pair 2 had the same direction (234.9 ms vs 167.3 ms). Source review found the 140 ms settle timer synthesizes a mousemove at cached coordinates even without new pointer motion, which can trigger Floating UI and caret geometry during typing. I am changing this to resume hover only on a real pointer move after the quiet period. These first three pairs are exploratory; I will repeat the comparisons against the final implementation.
Author
Owner

Committed 49fdf4985e5a07ab425b196b5db0eb51d591d3f1 (Resume Note hover after fresh pointer input).

The 140 ms scroll-settle timer no longer synthesizes a mousemove or triggers hit testing. Passive drag-handle input stays suppressed during scroll and until quiet; a real pointer move resumes it. Block hover actions use the same quiet-plus-fresh-move rule. Keyboard ownership and active dragging remain available.

Focused verification:

  • packages/editor: bunx vitest run src/extensions.dragHandle.test.ts — 1 file, 12 tests passed.
  • apps/web: bunx vitest run src/lib/editor/format/BlockHoverActions.svelte.test.ts — 1 file, 10 tests passed.

The three earlier performance pairs are exploratory because they predate this fix. I will rebuild and repeat the required comparisons with this implementation.

Committed `49fdf4985e5a07ab425b196b5db0eb51d591d3f1` (`Resume Note hover after fresh pointer input`). The 140 ms scroll-settle timer no longer synthesizes a mousemove or triggers hit testing. Passive drag-handle input stays suppressed during scroll and until quiet; a real pointer move resumes it. Block hover actions use the same quiet-plus-fresh-move rule. Keyboard ownership and active dragging remain available. Focused verification: - `packages/editor`: `bunx vitest run src/extensions.dragHandle.test.ts` — 1 file, 12 tests passed. - `apps/web`: `bunx vitest run src/lib/editor/format/BlockHoverActions.svelte.test.ts` — 1 file, 10 tests passed. The three earlier performance pairs are exploratory because they predate this fix. I will rebuild and repeat the required comparisons with this implementation.
Author
Owner

Post-fix verification update:

  • The full web suite passes: 302 files and 2,178 tests. bun run check passes after refreshing only the exact moved performance pins in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json; contracts/perf/ratchet.json is unchanged. Perf-lint reports PASS; 0 violations; 22544 scoped exceptions.
  • The production build completed, and the real API risk probe passed against it. Fresh 5k Note scroll reported maxInputDrift=0, maxClampPx=0; print produced a 3,583,629-byte PDF.
  • Fresh production screenshots include 24 Mac-platform-emulated states at 390/820/1440 px, light/dark, with mid-scroll and hover-after-scroll captures. I will attach the screenshots and raw performance outputs with the final report.
Post-fix verification update: - The full web suite passes: 302 files and 2,178 tests. `bun run check` passes after refreshing only the exact moved performance pins in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`; `contracts/perf/ratchet.json` is unchanged. Perf-lint reports `PASS; 0 violations; 22544 scoped exceptions`. - The production build completed, and the real API risk probe passed against it. Fresh 5k Note scroll reported `maxInputDrift=0`, `maxClampPx=0`; print produced a 3,583,629-byte PDF. - Fresh production screenshots include 24 Mac-platform-emulated states at 390/820/1440 px, light/dark, with mid-scroll and hover-after-scroll captures. I will attach the screenshots and raw performance outputs with the final report.
Author
Owner

Final-candidate pair 1 completed on perf-run, with base then candidate; locked load average was 0.01 at the start and 2.87 between revisions.

Note blocks Revision Cold open p50/p95 (ms) Warm open p50/p95 (ms) Scroll p95 (ms) Middle typing p95 (ms)
5,000 0743 baseline 1770.9/3938.7 1748.6/1748.6 250.0 105.1
5,000 candidate 1496.3/2213.7 1526.9/1526.9 216.5 190.5
20,000 0743 baseline 4453.9/4868.5 5142.5/5142.5 700.0 151.4
20,000 candidate 4394.1/5303.1 4628.3/4628.3 383.3 176.8

This is one of the five required pairs. Scroll improved but remains above the 50 ms target. Middle typing regressed in this pair at both sizes; I will use all five pairs before deciding whether this is a stable regression.

Final-candidate pair 1 completed on perf-run, with base then candidate; locked load average was 0.01 at the start and 2.87 between revisions. | Note blocks | Revision | Cold open p50/p95 (ms) | Warm open p50/p95 (ms) | Scroll p95 (ms) | Middle typing p95 (ms) | | ---: | --- | ---: | ---: | ---: | ---: | | 5,000 | 0743 baseline | 1770.9/3938.7 | 1748.6/1748.6 | 250.0 | 105.1 | | 5,000 | candidate | 1496.3/2213.7 | 1526.9/1526.9 | 216.5 | 190.5 | | 20,000 | 0743 baseline | 4453.9/4868.5 | 5142.5/5142.5 | 700.0 | 151.4 | | 20,000 | candidate | 4394.1/5303.1 | 4628.3/4628.3 | 383.3 | 176.8 | This is one of the five required pairs. Scroll improved but remains above the 50 ms target. Middle typing regressed in this pair at both sizes; I will use all five pairs before deciding whether this is a stable regression.
Author
Owner

Warm-open attribution completed for the current candidate (one traced reopen per size, local loopback on the locked perf VM). The fixture is plain Markdown with no Canvas or Drawing embeds.

  • 5k warm reopen first usable paint: 401.1 ms. Renderer event totals: IntersectionObserverController::computeIntersections 71.31 ms, EventDispatch 19.30 ms, FunctionCall 13.23 ms. HitTest was 10.75 ms.
  • 20k warm reopen first usable paint: 893.5 ms. IntersectionObserverController::computeIntersections 430.93 ms, HitTest 83.80 ms, Commit 66.18 ms.
  • The parent RunTask totals are not added to their child events. The CPU profile did not show a large app-level lowlight or full-document decoration function.

The plain fixture does not activate the shared embed observer, and NoteContents does not observe its one heading. The remaining intersection time is likely browser-managed content-visibility work. I am measuring a temporary normal-flow build against the current build before deciding whether removing that deferral is safe for both open and scroll.

The final 5k fling trace after the hover fix has no getCssDimensions or caret-position geometry entries; native intersection work remains 3,050.04 ms, with HitTest at 1,104.74 ms. This trace still misses the 50 ms scroll-frame p95 goal, so the full five-pair campaign remains necessary.

Warm-open attribution completed for the current candidate (one traced reopen per size, local loopback on the locked perf VM). The fixture is plain Markdown with no Canvas or Drawing embeds. - 5k warm reopen first usable paint: 401.1 ms. Renderer event totals: `IntersectionObserverController::computeIntersections` 71.31 ms, `EventDispatch` 19.30 ms, `FunctionCall` 13.23 ms. `HitTest` was 10.75 ms. - 20k warm reopen first usable paint: 893.5 ms. `IntersectionObserverController::computeIntersections` 430.93 ms, `HitTest` 83.80 ms, `Commit` 66.18 ms. - The parent `RunTask` totals are not added to their child events. The CPU profile did not show a large app-level lowlight or full-document decoration function. The plain fixture does not activate the shared embed observer, and NoteContents does not observe its one heading. The remaining intersection time is likely browser-managed `content-visibility` work. I am measuring a temporary normal-flow build against the current build before deciding whether removing that deferral is safe for both open and scroll. The final 5k fling trace after the hover fix has no `getCssDimensions` or caret-position geometry entries; native intersection work remains 3,050.04 ms, with `HitTest` at 1,104.74 ms. This trace still misses the 50 ms scroll-frame p95 goal, so the full five-pair campaign remains necessary.
Author
Owner

The one-pair diagnostic for browser-managed content-visibility is complete. The temporary normal-flow build is rejected for this job: it lowered 20k scroll p95 from 333.4 ms to 133.3 ms, but 20k cold-open p95 rose from 5469.4 ms to 6261.6 ms and middle-typing p95 rose from 159.4 ms to 213.2 ms. At 5k, scroll p95 changed only from 216.6 ms to 199.9 ms, still well above 50 ms. These are single-pair exploratory values, not final comparisons.

I restored the source to the current content-visibility behavior. It remains because removing the deferral creates a measured 20k typing/open regression and still misses the scroll target. The final five-pair campaign will use the current source.

The one-pair diagnostic for browser-managed `content-visibility` is complete. The temporary normal-flow build is rejected for this job: it lowered 20k scroll p95 from 333.4 ms to 133.3 ms, but 20k cold-open p95 rose from 5469.4 ms to 6261.6 ms and middle-typing p95 rose from 159.4 ms to 213.2 ms. At 5k, scroll p95 changed only from 216.6 ms to 199.9 ms, still well above 50 ms. These are single-pair exploratory values, not final comparisons. I restored the source to the current content-visibility behavior. It remains because removing the deferral creates a measured 20k typing/open regression and still misses the scroll target. The final five-pair campaign will use the current source.
Author
Owner

Five final-source interleaved pairs are complete on the locked perf VM. Each run used 20 middle-typing key samples, 102 fling-frame samples, two cold opens and one warm reopen; reported figures below are medians of the five per-run percentiles. No slow samples were filtered. The locked load averages are in the attached raw profiles.

Note size Comparison Cold open p95 Warm open p95 Scroll-frame p95 Middle typing p95
5k 0743 base → candidate 2270.5 → 2213.7 ms 1515.3 → 1526.9 ms 250.0 → 183.3 ms 111.7 → 114.1 ms
20k 0743 base → candidate 4868.5 → 5209.0 ms 4439.3 → 4628.3 ms 750.0 → 350.0 ms 150.9 → 172.1 ms
5k origin/dev → candidate 2323.5 → 2045.0 ms 1576.2 → 1573.7 ms 216.7 → 216.6 ms 172.6 → 111.3 ms
20k origin/dev → candidate 5886.0 → 5209.7 ms 4765.4 → 4507.2 ms 233.4 → 399.9 ms 178.1 → 177.3 ms

The required 5k scroll p95 ≤50 ms target is not met (candidate median 183.3 ms vs base, 216.6 ms vs origin/dev). At 20k the candidate improves scroll vs the 0743 base but regresses vs origin/dev. Middle typing p95 regresses vs base by 2.4 ms at 5k and 21.2 ms at 20k; it improves vs origin/dev at 5k and is effectively flat at 20k. These misses are retained as known gaps. The no-content-visibility variant was rejected: its single 20k diagnostic improved scroll but worsened cold open by 792 ms and middle typing by 53.8 ms, and still missed the scroll target.

Five final-source interleaved pairs are complete on the locked perf VM. Each run used 20 middle-typing key samples, 102 fling-frame samples, two cold opens and one warm reopen; reported figures below are medians of the five per-run percentiles. No slow samples were filtered. The locked load averages are in the attached raw profiles. | Note size | Comparison | Cold open p95 | Warm open p95 | Scroll-frame p95 | Middle typing p95 | | ---: | --- | ---: | ---: | ---: | ---: | | 5k | 0743 base → candidate | 2270.5 → 2213.7 ms | 1515.3 → 1526.9 ms | 250.0 → 183.3 ms | 111.7 → 114.1 ms | | 20k | 0743 base → candidate | 4868.5 → 5209.0 ms | 4439.3 → 4628.3 ms | 750.0 → 350.0 ms | 150.9 → 172.1 ms | | 5k | origin/dev → candidate | 2323.5 → 2045.0 ms | 1576.2 → 1573.7 ms | 216.7 → 216.6 ms | 172.6 → 111.3 ms | | 20k | origin/dev → candidate | 5886.0 → 5209.7 ms | 4765.4 → 4507.2 ms | 233.4 → 399.9 ms | 178.1 → 177.3 ms | The required 5k scroll p95 ≤50 ms target is not met (candidate median 183.3 ms vs base, 216.6 ms vs origin/dev). At 20k the candidate improves scroll vs the 0743 base but regresses vs origin/dev. Middle typing p95 regresses vs base by 2.4 ms at 5k and 21.2 ms at 20k; it improves vs origin/dev at 5k and is effectively flat at 20k. These misses are retained as known gaps. The no-content-visibility variant was rejected: its single 20k diagnostic improved scroll but worsened cold open by 792 ms and middle typing by 53.8 ms, and still missed the scroll target.
Author
Owner

Finding in the optional five-minute memory profile: its save assertion counts 20 trace-only typing keys even when trace capture is disabled. The profile typed 901 keys and found 961 z characters in both the live Note and persisted Note, but compared them with 981 and reported no_lost_keystrokes=false. This is a harness accounting error, not lost Note data. I am correcting the expected-count formula and will repeat this profile before reporting CPU/RSS.

Finding in the optional five-minute memory profile: its save assertion counts 20 trace-only typing keys even when trace capture is disabled. The profile typed 901 keys and found 961 `z` characters in both the live Note and persisted Note, but compared them with 981 and reported `no_lost_keystrokes=false`. This is a harness accounting error, not lost Note data. I am correcting the expected-count formula and will repeat this profile before reporting CPU/RSS.
Author
Owner

The corrected five-minute 20k candidate profile used commit d251c0346f40f205c30e57a1c00eb3da5fab76d1 and the locked perf VM. The no-trace accounting check passes: 1,020 sustained keys plus 60 sampled keys were present in the live Note and persisted Note; save completed in 3,274.9 ms. Heap grew 12.8% (55.5 MiB to 62.6 MiB).

Across the five-minute typing burst, browser process-tree mean CPU was 188.92% (peak 267.86%), mean RSS 841,766,353 bytes (peak 956,846,080); server mean CPU was 105.57% (peak 203.81%), mean RSS 1,234,868,523 bytes (peak 1,380,311,040). This is one candidate burst profile, not a five-pair CPU/RSS distribution. Locked load averages were 1.86 2.71 2.58 at start and 3.82 3.73 3.10 at end.

The corrected five-minute 20k candidate profile used commit d251c0346f40f205c30e57a1c00eb3da5fab76d1 and the locked perf VM. The no-trace accounting check passes: 1,020 sustained keys plus 60 sampled keys were present in the live Note and persisted Note; save completed in 3,274.9 ms. Heap grew 12.8% (55.5 MiB to 62.6 MiB). Across the five-minute typing burst, browser process-tree mean CPU was 188.92% (peak 267.86%), mean RSS 841,766,353 bytes (peak 956,846,080); server mean CPU was 105.57% (peak 203.81%), mean RSS 1,234,868,523 bytes (peak 1,380,311,040). This is one candidate burst profile, not a five-pair CPU/RSS distribution. Locked load averages were 1.86 2.71 2.58 at start and 3.82 3.73 3.10 at end.
Author
Owner

Correction to the preceding RSS profile note: its raw environment metadata contains the mistyped PERF_PROFILE_COMMIT d251c0346f40f205c30e57a1c00eb3da5fab76d1. The actual source commit used for the run was d251c03463eb7f9214476c2d12d5d421d3e8e096. That commit changes only the no-trace benchmark's expected-key accounting; the production SPA assets are unchanged from 682c071e2. The attached evidence keeps the raw file and a corrected copy with this provenance note; all measured values are unchanged.

Correction to the preceding RSS profile note: its raw environment metadata contains the mistyped PERF_PROFILE_COMMIT `d251c0346f40f205c30e57a1c00eb3da5fab76d1`. The actual source commit used for the run was `d251c03463eb7f9214476c2d12d5d421d3e8e096`. That commit changes only the no-trace benchmark's expected-key accounting; the production SPA assets are unchanged from `682c071e2`. The attached evidence keeps the raw file and a corrected copy with this provenance note; all measured values are unchanged.
Author
Owner

The native Mac Chrome round is waiting on the required shared-device lock. As of 2026-10-08 23:14 UTC, /tmp/mac-bench.lock still names notifread-1387 (PID 29225), started 22:01:55 UTC with a 60-minute estimate; that process is active. I did not remove or override its lock. The production screenshot set uses macOS platform emulation and is attached; the requested native Mac three-pair timing round remains pending until the device is free.

The native Mac Chrome round is waiting on the required shared-device lock. As of 2026-10-08 23:14 UTC, `/tmp/mac-bench.lock` still names `notifread-1387` (PID 29225), started 22:01:55 UTC with a 60-minute estimate; that process is active. I did not remove or override its lock. The production screenshot set uses macOS platform emulation and is attached; the requested native Mac three-pair timing round remains pending until the device is free.
Author
Owner

The bounded 15-minute Mac launch attempt exited without starting Chrome. As of 2026-10-08 23:43 UTC, /tmp/mac-bench.lock still named the active notifread-1387 process (PID 29225), started 22:01:55 UTC with a 60-minute estimate. I did not override the lock. I am leaving a short final window for the native three-pair round; if the lock remains active, the report will list this requested measurement as uncompleted.

The bounded 15-minute Mac launch attempt exited without starting Chrome. As of 2026-10-08 23:43 UTC, `/tmp/mac-bench.lock` still named the active `notifread-1387` process (PID 29225), started 22:01:55 UTC with a 60-minute estimate. I did not override the lock. I am leaving a short final window for the native three-pair round; if the lock remains active, the report will list this requested measurement as uncompleted.
Author
Owner

Forgejo #1481 final report

Head: d251c03463eb7f9214476c2d12d5d421d3e8e096. The branch merges origin/dev once at bba5c50b2; no push, deploy or merge to dev was performed.

Built

  • Block hover and drag-handle geometry no longer runs during scroll. The existing 140 ms quiet period remains; passive hover resumes after a fresh pointer move. Keyboard actions and active dragging remain available.
  • Canvas previews and Drawing blocks share one IntersectionObserver with a 300 px viewport margin. It is disconnected after the last target leaves.
  • The large Note benchmark can connect to a remote Playwright BrowserServer for native Mac Chrome runs. Traced warm opens stay separate from untraced latency samples.
  • The 20k no-trace memory profile now counts only keys that the selected run actually typed.

Files changed by this issue:

  • apps/web/e2e/bignote-1349-risk.mjs
  • apps/web/src/lib/canvas/CanvasPreview.svelte
  • apps/web/src/lib/canvas/DrawingBlock.svelte
  • apps/web/src/lib/editor/format/BlockHoverActions.svelte
  • apps/web/src/lib/editor/format/BlockHoverActions.svelte.test.ts
  • apps/web/src/lib/notes/noteViewport.ts
  • apps/web/src/lib/notes/noteViewport.test.ts
  • bench/bignote-1349.mjs
  • contracts/perf/adoption-1058.json
  • contracts/perf/exceptions.json
  • packages/editor/src/extensions.ts
  • packages/editor/src/extensions.dragHandle.test.ts

The only visible controls remain the existing shared PillGroup, FormatButton, Pill and Menu components. No local control styling was added.

Performance

Five interleaved pairs ran on the locked perf VM at 5k and 20k blocks for each comparison. Open p50/p95/max uses every raw open sample across five runs (10 cold opens and 5 warm reopens). Scroll and typing p50/p95 are medians of the five per-run stats; max is the largest frame/key sample across those runs. Each run measured 20 middle-typing keys and about 102 scroll frames. Slow values remain in the raw profiles.

Note Comparison Cold open p50/p95/max (ms) Warm reopen p50/p95/max (ms) Scroll p50/p95/max (ms) Middle typing p50/p95/max (ms)
5k 0743 base 1770.9 / 3938.7 / 3938.7 1515.3 / 1748.6 / 1748.6 116.7 / 250.0 / 466.7 54.1 / 111.7 / 177.9
5k candidate 1702.4 / 2612.0 / 2612.0 1526.9 / 1558.6 / 1558.6 100.0 / 183.3 / 250.1 51.8 / 114.1 / 236.3
20k 0743 base 4591.4 / 5225.7 / 5225.7 4439.3 / 5142.5 / 5142.5 333.3 / 750.0 / 983.3 77.9 / 150.9 / 180.7
20k candidate 5031.7 / 5605.6 / 5605.6 4628.3 / 5134.5 / 5134.5 233.4 / 350.0 / 500.0 72.4 / 172.1 / 326.8
5k origin/dev 2031.6 / 5263.4 / 5263.4 1576.2 / 1635.2 / 1635.2 116.6 / 216.7 / 266.7 62.5 / 172.6 / 246.3
5k candidate 1850.8 / 2165.4 / 2165.4 1573.7 / 1701.8 / 1701.8 116.6 / 216.6 / 283.3 44.4 / 111.3 / 172.0
20k origin/dev 5734.4 / 6142.2 / 6142.2 4765.4 / 4958.5 / 4958.5 100.0 / 233.4 / 416.6 135.8 / 178.1 / 262.8
20k candidate 4670.4 / 5451.4 / 5451.4 4507.2 / 4727.2 / 4727.2 250.0 / 399.9 / 500.0 71.7 / 177.3 / 332.0

The 5k fling p95 target of 50 ms is not met: candidate median is 183.3 ms against the base and 216.6 ms against origin/dev. Per-frame p95 still grows with Note size: 183.3 to 350.0 ms against the base, and 216.6 to 399.9 ms against origin/dev. Middle typing p95 regresses against the base by 2.4 ms at 5k and 21.2 ms at 20k. It improves at 5k and is flat at 20k against origin/dev. Warm reopen remains about 1.5 s at 5k and 4.5–4.6 s at 20k, above the §59 cached-open budget of 100 ms.

The 5k fling trace had no Floating UI getCssDimensions or caretPositionFromPoint events after the hover change. Native IntersectionObserverController::computeIntersections remained the largest total at 3050.04 ms; HitTest was 1104.74 ms, Layout 523.09 ms and UpdateLayoutTree 97.03 ms. The original trace had 3617 ms intersection work, 1456 ms getCssDimensions and 707 ms caret geometry.

Traced warm reopen first usable paint was 401.1 ms at 5k and 893.5 ms at 20k. The top three renderer event totals were 5k: intersections 71.31 ms, EventDispatch 19.30 ms, FunctionCall 13.23 ms; 20k: intersections 430.93 ms, HitTest 83.80 ms, Commit 66.18 ms. These are one traced sample per size, separate from the untraced latency table. No large app-level lowlight or full-document decoration function appeared in the CPU sample.

A single no-content-visibility diagnostic lowered 20k scroll p95 from 333.4 to 133.3 ms, but raised cold-open p95 by 792 ms and middle typing p95 by 53.8 ms; 5k scroll improved only 16.7 ms. I retained content-visibility because the diagnostic still missed the scroll target and regressed typing/open.

A corrected five-minute 20k candidate profile saved all 1,080 expected z characters. Browser mean/peak CPU was 188.92% / 267.86%, with mean/peak RSS 841,766,353 / 956,846,080 bytes. Server mean/peak CPU was 105.57% / 203.81%, with mean/peak RSS 1,234,868,523 / 1,380,311,040 bytes. Heap growth was 12.8%; durable save took 3,274.9 ms. This is one burst profile, not a five-pair CPU/RSS distribution. Its raw profile has a separate corrected provenance copy because the first PERF_PROFILE_COMMIT argument was mistyped; the corrected source commit is this report's head, and the production SPA assets did not change in that benchmark-only commit.

No directly comparable controlled large-Note profile exists in docs/perf/baseline.json; the requested 0743 and origin/dev builds are the comparison baselines.

Screenshots and risk probe

The production risk probe passed with zero scroll input drift and zero clamp; print produced a 3,583,629-byte PDF. Twenty-four production captures use the macOS platform emulation at 390/820/1440 px in light/dark, showing top, middle, middle-hover and typed states. A separate shortcut capture is also attached. The reviewer should assess the captures; this report does not judge their visual quality.

Middle-scroll and settled-hover captures:

Native Mac Chrome

The requested native Mac three-pair comparison did not run. At 23:59 UTC, a lock check on the Mac showed /tmp/mac-bench.lock still held with the entry notifread-1387 29225 2026-10-08T22:01:55Z 60. I did not remove or override it. A separate launch attempt failed to bind local tunnel port 39850 before BrowserServer readiness; no Chrome session started. The 24 production captures use macOS platform emulation; they are not native Mac timing evidence.

If the shared device is free in the merge round, run flock -w 7200 ~/.local/state/codex-jobs/calternal/macvm.lock artifacts/bigscroll-1481/run-mac-locked.sh. It takes /tmp/mac-bench.lock before launching actual headful Mac Chrome, then runs three alternating 5k pairs against 0743. The transport is HTTP/1.1 over SSH -L/-R; the harness records requestStart - fetchStart p95/max as queue-plus-connection-setup bounds, because Chrome does not expose socket-pool queue time separately.

Gates

cd packages/editor && bun run test

 Test Files  29 passed (29)
      Tests  513 passed (513)

cd apps/web && bun run check

svelte-check found 0 errors and 4 warnings in 2 files

cd apps/web && bun run test --maxWorkers=2

 Test Files  302 passed (302)
      Tests  2178 passed (2178)
   Start at  23:42:29
   Duration  510.28s (environment 28%, transform 27%, import 24%, tests 16%, setup 5%)

Perf lint: perf-lint: PASS; 0 violations; 22544 scoped exceptions. It refreshed exact pins in contracts/perf/exceptions.json and contracts/perf/adoption-1058.json; the ratchet was not changed. No Rust files changed, so no Rust crate gates ran.

UX gaps closed / left

Closed: passive hover geometry during scroll; per-embed observer duplication; post-scroll hover only resumes on a real pointer move; scroll-then-hover regression coverage; real production mid-scroll and settled-hover screenshots. Existing keyboard and active-drag behavior remains available.

Left: 5k scroll p95 ≤50 ms; size-independent per-frame work; cached-open ≤100 ms; middle typing p95 not regressing against the 0743 base. The Mac three-pair comparison is pending the shared device lock.

Decisions and expected cost

  • Keep the existing 140 ms hover settle and require fresh pointer input before passive geometry resumes. This avoids synthetic movement that causes a new getBoundingClientRect or caret read. Active drag and keyboard actions remain immediate.
  • Use one shared observer with the existing 300 px viewport lead-in for Canvas previews and Drawing blocks. Disconnect it when the final target leaves.
  • Keep content-visibility after the controlled diagnostic showed worse 20k open and typing results without reaching the scroll target.
  • Observer storage is proportional to mounted Note embeds, not Note blocks; one native observer handles those targets. Hover geometry work occurs after a fresh pointer move, not on each scroll event. Browser-managed content visibility, hit testing and layout still scale with total Note size; the p95 data shows that remaining cost.
# Forgejo #1481 final report Head: `d251c03463eb7f9214476c2d12d5d421d3e8e096`. The branch merges `origin/dev` once at `bba5c50b2`; no push, deploy or merge to `dev` was performed. ## Built - Block hover and drag-handle geometry no longer runs during scroll. The existing 140 ms quiet period remains; passive hover resumes after a fresh pointer move. Keyboard actions and active dragging remain available. - Canvas previews and Drawing blocks share one IntersectionObserver with a 300 px viewport margin. It is disconnected after the last target leaves. - The large Note benchmark can connect to a remote Playwright BrowserServer for native Mac Chrome runs. Traced warm opens stay separate from untraced latency samples. - The 20k no-trace memory profile now counts only keys that the selected run actually typed. Files changed by this issue: - `apps/web/e2e/bignote-1349-risk.mjs` - `apps/web/src/lib/canvas/CanvasPreview.svelte` - `apps/web/src/lib/canvas/DrawingBlock.svelte` - `apps/web/src/lib/editor/format/BlockHoverActions.svelte` - `apps/web/src/lib/editor/format/BlockHoverActions.svelte.test.ts` - `apps/web/src/lib/notes/noteViewport.ts` - `apps/web/src/lib/notes/noteViewport.test.ts` - `bench/bignote-1349.mjs` - `contracts/perf/adoption-1058.json` - `contracts/perf/exceptions.json` - `packages/editor/src/extensions.ts` - `packages/editor/src/extensions.dragHandle.test.ts` The only visible controls remain the existing shared `PillGroup`, `FormatButton`, `Pill` and `Menu` components. No local control styling was added. ## Performance Five interleaved pairs ran on the locked perf VM at 5k and 20k blocks for each comparison. Open p50/p95/max uses every raw open sample across five runs (10 cold opens and 5 warm reopens). Scroll and typing p50/p95 are medians of the five per-run stats; max is the largest frame/key sample across those runs. Each run measured 20 middle-typing keys and about 102 scroll frames. Slow values remain in the raw profiles. | Note | Comparison | Cold open p50/p95/max (ms) | Warm reopen p50/p95/max (ms) | Scroll p50/p95/max (ms) | Middle typing p50/p95/max (ms) | | ---: | --- | ---: | ---: | ---: | ---: | | 5k | 0743 base | 1770.9 / 3938.7 / 3938.7 | 1515.3 / 1748.6 / 1748.6 | 116.7 / 250.0 / 466.7 | 54.1 / 111.7 / 177.9 | | 5k | candidate | 1702.4 / 2612.0 / 2612.0 | 1526.9 / 1558.6 / 1558.6 | 100.0 / 183.3 / 250.1 | 51.8 / 114.1 / 236.3 | | 20k | 0743 base | 4591.4 / 5225.7 / 5225.7 | 4439.3 / 5142.5 / 5142.5 | 333.3 / 750.0 / 983.3 | 77.9 / 150.9 / 180.7 | | 20k | candidate | 5031.7 / 5605.6 / 5605.6 | 4628.3 / 5134.5 / 5134.5 | 233.4 / 350.0 / 500.0 | 72.4 / 172.1 / 326.8 | | 5k | origin/dev | 2031.6 / 5263.4 / 5263.4 | 1576.2 / 1635.2 / 1635.2 | 116.6 / 216.7 / 266.7 | 62.5 / 172.6 / 246.3 | | 5k | candidate | 1850.8 / 2165.4 / 2165.4 | 1573.7 / 1701.8 / 1701.8 | 116.6 / 216.6 / 283.3 | 44.4 / 111.3 / 172.0 | | 20k | origin/dev | 5734.4 / 6142.2 / 6142.2 | 4765.4 / 4958.5 / 4958.5 | 100.0 / 233.4 / 416.6 | 135.8 / 178.1 / 262.8 | | 20k | candidate | 4670.4 / 5451.4 / 5451.4 | 4507.2 / 4727.2 / 4727.2 | 250.0 / 399.9 / 500.0 | 71.7 / 177.3 / 332.0 | The 5k fling p95 target of 50 ms is not met: candidate median is 183.3 ms against the base and 216.6 ms against origin/dev. Per-frame p95 still grows with Note size: 183.3 to 350.0 ms against the base, and 216.6 to 399.9 ms against origin/dev. Middle typing p95 regresses against the base by 2.4 ms at 5k and 21.2 ms at 20k. It improves at 5k and is flat at 20k against origin/dev. Warm reopen remains about 1.5 s at 5k and 4.5–4.6 s at 20k, above the §59 cached-open budget of 100 ms. The 5k fling trace had no Floating UI `getCssDimensions` or `caretPositionFromPoint` events after the hover change. Native `IntersectionObserverController::computeIntersections` remained the largest total at 3050.04 ms; `HitTest` was 1104.74 ms, `Layout` 523.09 ms and `UpdateLayoutTree` 97.03 ms. The original trace had 3617 ms intersection work, 1456 ms `getCssDimensions` and 707 ms caret geometry. Traced warm reopen first usable paint was 401.1 ms at 5k and 893.5 ms at 20k. The top three renderer event totals were 5k: intersections 71.31 ms, EventDispatch 19.30 ms, FunctionCall 13.23 ms; 20k: intersections 430.93 ms, HitTest 83.80 ms, Commit 66.18 ms. These are one traced sample per size, separate from the untraced latency table. No large app-level lowlight or full-document decoration function appeared in the CPU sample. A single no-content-visibility diagnostic lowered 20k scroll p95 from 333.4 to 133.3 ms, but raised cold-open p95 by 792 ms and middle typing p95 by 53.8 ms; 5k scroll improved only 16.7 ms. I retained `content-visibility` because the diagnostic still missed the scroll target and regressed typing/open. A corrected five-minute 20k candidate profile saved all 1,080 expected `z` characters. Browser mean/peak CPU was 188.92% / 267.86%, with mean/peak RSS 841,766,353 / 956,846,080 bytes. Server mean/peak CPU was 105.57% / 203.81%, with mean/peak RSS 1,234,868,523 / 1,380,311,040 bytes. Heap growth was 12.8%; durable save took 3,274.9 ms. This is one burst profile, not a five-pair CPU/RSS distribution. Its raw profile has a separate corrected provenance copy because the first `PERF_PROFILE_COMMIT` argument was mistyped; the corrected source commit is this report's head, and the production SPA assets did not change in that benchmark-only commit. No directly comparable controlled large-Note profile exists in `docs/perf/baseline.json`; the requested 0743 and origin/dev builds are the comparison baselines. ## Screenshots and risk probe The production risk probe passed with zero scroll input drift and zero clamp; print produced a 3,583,629-byte PDF. Twenty-four production captures use the macOS platform emulation at 390/820/1440 px in light/dark, showing top, middle, middle-hover and typed states. A separate shortcut capture is also attached. The reviewer should assess the captures; this report does not judge their visual quality. Middle-scroll and settled-hover captures: - [390 light middle](https://git.kayg.org/attachments/6cafb64b-1758-4134-8812-6821034879f5), [390 light hover](https://git.kayg.org/attachments/b6717c64-5bd4-4b03-a273-012e560900ff), [390 dark middle](https://git.kayg.org/attachments/61604b90-ec6a-4cb4-8aa6-7a6a51477532), [390 dark hover](https://git.kayg.org/attachments/761b7435-df9f-4680-b78d-ee842c774905) - [820 light middle](https://git.kayg.org/attachments/dd298a5c-e98b-4598-926b-b7adaaa814ac), [820 light hover](https://git.kayg.org/attachments/14fa1bdd-785c-4ccd-8124-f4d53785012f), [820 dark middle](https://git.kayg.org/attachments/69d1ccf3-082b-47c7-aaa8-82792add5f62), [820 dark hover](https://git.kayg.org/attachments/c79418e1-e854-49b7-a5e3-360355f24b1e) - [1440 light middle](https://git.kayg.org/attachments/c2f2b099-ab14-4127-86ed-b15149744f1c), [1440 light hover](https://git.kayg.org/attachments/383d70d1-e3ec-4c6d-94f6-04b96745d135), [1440 dark middle](https://git.kayg.org/attachments/4cb8e60b-5292-4e7a-9ecb-835033582f68), [1440 dark hover](https://git.kayg.org/attachments/a645b647-5946-4f3f-9af2-5facce7ea116) - [Print PDF](https://git.kayg.org/attachments/7b225551-2dd3-453d-819e-7b74f2ad9137) · [Risk probe log](https://git.kayg.org/attachments/7a239825-d29f-43cc-83e8-901c9d2752d7) · [Performance evidence bundle](https://git.kayg.org/attachments/ed4f9c4d-30cd-4a14-9cda-c2ed096e8d69) ## Native Mac Chrome The requested native Mac three-pair comparison did not run. At 23:59 UTC, a lock check on the Mac showed `/tmp/mac-bench.lock` still held with the entry `notifread-1387 29225 2026-10-08T22:01:55Z 60`. I did not remove or override it. A separate launch attempt failed to bind local tunnel port 39850 before BrowserServer readiness; no Chrome session started. The 24 production captures use macOS platform emulation; they are not native Mac timing evidence. If the shared device is free in the merge round, run `flock -w 7200 ~/.local/state/codex-jobs/calternal/macvm.lock artifacts/bigscroll-1481/run-mac-locked.sh`. It takes `/tmp/mac-bench.lock` before launching actual headful Mac Chrome, then runs three alternating 5k pairs against 0743. The transport is HTTP/1.1 over SSH `-L`/`-R`; the harness records `requestStart - fetchStart` p95/max as queue-plus-connection-setup bounds, because Chrome does not expose socket-pool queue time separately. ## Gates `cd packages/editor && bun run test` ``` Test Files 29 passed (29) Tests 513 passed (513) ``` `cd apps/web && bun run check` ``` svelte-check found 0 errors and 4 warnings in 2 files ``` `cd apps/web && bun run test --maxWorkers=2` ``` Test Files 302 passed (302) Tests 2178 passed (2178) Start at 23:42:29 Duration 510.28s (environment 28%, transform 27%, import 24%, tests 16%, setup 5%) ``` Perf lint: `perf-lint: PASS; 0 violations; 22544 scoped exceptions`. It refreshed exact pins in `contracts/perf/exceptions.json` and `contracts/perf/adoption-1058.json`; the ratchet was not changed. No Rust files changed, so no Rust crate gates ran. ## UX gaps closed / left Closed: passive hover geometry during scroll; per-embed observer duplication; post-scroll hover only resumes on a real pointer move; scroll-then-hover regression coverage; real production mid-scroll and settled-hover screenshots. Existing keyboard and active-drag behavior remains available. Left: 5k scroll p95 ≤50 ms; size-independent per-frame work; cached-open ≤100 ms; middle typing p95 not regressing against the 0743 base. The Mac three-pair comparison is pending the shared device lock. ## Decisions and expected cost - Keep the existing 140 ms hover settle and require fresh pointer input before passive geometry resumes. This avoids synthetic movement that causes a new `getBoundingClientRect` or caret read. Active drag and keyboard actions remain immediate. - Use one shared observer with the existing 300 px viewport lead-in for Canvas previews and Drawing blocks. Disconnect it when the final target leaves. - Keep `content-visibility` after the controlled diagnostic showed worse 20k open and typing results without reaching the scroll target. - Observer storage is proportional to mounted Note embeds, not Note blocks; one native observer handles those targets. Hover geometry work occurs after a fresh pointer move, not on each scroll event. Browser-managed content visibility, hit testing and layout still scale with total Note size; the p95 data shows that remaining cost.
Author
Owner

Observer audit addendum: the benchmark Note has one heading and no Canvas or Drawing embeds, so its Note Contents observer is inactive and the shared embed observer has no targets. NoteCards uses one ResizeObserver on the host parent and editor DOM. This leaves browser content-visibility: auto on the Note paragraphs as the source of the large native intersection total in this benchmark. Disabling it improved 5k scroll p95 by only 16.7 ms, while worsening 20k cold-open p95 by 792 ms and middle-typing p95 by 53.8 ms, so I retained it.

Observer audit addendum: the benchmark Note has one heading and no Canvas or Drawing embeds, so its Note Contents observer is inactive and the shared embed observer has no targets. NoteCards uses one ResizeObserver on the host parent and editor DOM. This leaves browser `content-visibility: auto` on the Note paragraphs as the source of the large native intersection total in this benchmark. Disabling it improved 5k scroll p95 by only 16.7 ms, while worsening 20k cold-open p95 by 792 ms and middle-typing p95 by 53.8 ms, so I retained it.
Author
Owner

Observer audit addendum: the benchmark Note has one heading and no Canvas or Drawing embeds, so its Note Contents observer is inactive and the shared embed observer has no targets. NoteCards uses one ResizeObserver on the host parent and editor DOM. This leaves browser content-visibility: auto on the Note paragraphs as the source of the large native intersection total in this benchmark. Disabling it improved 5k scroll p95 by only 16.7 ms, while worsening 20k cold-open p95 by 792 ms and middle-typing p95 by 53.8 ms, so I retained it.

Mac runner addendum: after the 39850 tunnel bind error, I updated the ignored resume helper to use alternate ports 41750/41749. A read-only Mac port check found those ports free. I did not retry because /tmp/mac-bench.lock remains held by the other job; this tunnel configuration is unverified.

Observer audit addendum: the benchmark Note has one heading and no Canvas or Drawing embeds, so its Note Contents observer is inactive and the shared embed observer has no targets. NoteCards uses one ResizeObserver on the host parent and editor DOM. This leaves browser `content-visibility: auto` on the Note paragraphs as the source of the large native intersection total in this benchmark. Disabling it improved 5k scroll p95 by only 16.7 ms, while worsening 20k cold-open p95 by 792 ms and middle-typing p95 by 53.8 ms, so I retained it. Mac runner addendum: after the 39850 tunnel bind error, I updated the ignored resume helper to use alternate ports 41750/41749. A read-only Mac port check found those ports free. I did not retry because `/tmp/mac-bench.lock` remains held by the other job; this tunnel configuration is unverified.
Author
Owner

Partial improvement deployed in merge round 35c (build 5a2c02c13). Left open: target not yet met.

Partial improvement deployed in merge round 35c (build 5a2c02c13). Left open: target not yet met.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
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-v0#1481
No description provided.