hermes-agent/apps/desktop/src/hooks
Brooklyn Nicholson 31d49f0dfc perf(desktop): share one ResizeObserver instead of one per consumer
A CDP trace of one sash drag settled what the render counters could not.
I had assumed the remaining cost was layout/paint; it was not:

  script 6770ms | style 1866ms | layout 71ms

Layout was never the problem. The top attributable callsite in our own
code was use-resize-observer.ts at 977ms.

Counting the callbacks named the mechanism exactly: 8,620 ResizeObserver
instances constructed, and during a 40-move drag 2,600 callbacks each
carrying exactly ONE entry — 65 separate callbacks per pointermove. Every
consumer owned a private observer, so N elements resizing under a common
ancestor meant N trips through the observer machinery instead of one
batched delivery. With five mounted tiles that is ~100 user bubbles, each
with its own observer, all woken by a width change.

One shared observer with a WeakMap of target -> handlers. Callers keep
their exact contract: a handler observing several elements is still
invoked once with all of its entries, and unobserve happens when the last
handler for an element goes away.

Verified by trace, before -> after:

  use-resize-observer   977ms -> 42.5ms   (-96%)
  style recalc         1866ms -> 1145ms   (-39%)
  total script         6770ms -> 3929ms   (-42%)

Callback count 2,600 -> 43: one delivery per frame instead of 65.

Adds the two probes that found it. diag-drag-trace.mjs takes a real
timeline trace and prints the style/layout/script split plus the top
script callsites — that split is what disproved the layout theory.
diag-ro-storm.mjs counts RO callbacks vs entries, which is what
distinguished 'a few expensive calls' from 'very many cheap ones'.
2026-07-26 19:56:55 -05:00
..
use-delayed-true.ts feat(desktop): add shared project UI primitives 2026-06-25 16:40:27 -05:00
use-image-download.ts fix(desktop): keep generated images in the tool slot, not inline 2026-06-13 02:42:15 -05:00
use-media-query.ts Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
use-mobile.ts Add Hermes desktop app (#20059) 2026-05-31 17:46:56 -05:00
use-resize-observer.ts perf(desktop): share one ResizeObserver instead of one per consumer 2026-07-26 19:56:55 -05:00
use-theme-epoch.ts refactor(desktop): share theme-repaint observer; memory-graph depth polish 2026-06-30 02:06:29 -05:00