Skip to content

perf: move cold hydration scans and LIS marking out of the hot diff functions - #5229

Closed
JoviDeCroock wants to merge 3 commits into
mainfrom
JoviDeCroock/extract-cold-diff-paths
Closed

perf: move cold hydration scans and LIS marking out of the hot diff functions#5229
JoviDeCroock wants to merge 3 commits into
mainfrom
JoviDeCroock/extract-cold-diff-paths

Conversation

@JoviDeCroock

@JoviDeCroock JoviDeCroock commented Sep 2, 2026

Copy link
Copy Markdown
Member

Note

This PR was authored by an LLM (Claude Fable 5.1) during the v11 release-readiness audit; Jovi reviewed the change and the tests.

Summary

Pure refactor, no behaviour change. Three cold code paths that only run on suspended or streamed hydration and on genuine reorders lived inline in the hottest functions:

  • the resume scan at the top of diff()collectExcess()
  • the suspend-side marker scan in diff()'s catch block → suspendVNode()
  • the LIS move-marking pass in constructNewChildrenArray()markMoves()

Why

While profiling the rc.1 vs 10.29.8 gap on the text-update and replace1k benches, both turned out to be warm-up effects: warmed up, v11 is faster than v10, but the benches measure the first 100 renders / the 6th run, where the interpreter and baseline tiers dominate and tier-up timing matters. V8 bytecode for diff() had grown from 2502 to 2923 bytes and constructNewChildrenArray() from 657 to 751, which delays optimisation of both. After extraction they are 2197 and 554 bytes, below their v10 sizes.

Cold, interleaved medians over 60 fresh pages (CDP harness, minified bundles):

bundle text-update, 100 cold renders
10.29.8 1.54 ms
main 1.67 ms
this PR 1.60 ms

replace1k is unchanged by this (its residual is diffuse tier-up timing). Core brotli: 4428 → 4430 B.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

📊 Tachometer Benchmark Results

Summary

duration

  • create10k: unsure 🔍 -1% - +1% (-6.43ms - +6.32ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -1% - +1% (-0.21ms - +0.14ms)
    preact-local vs preact-main
  • hydrate1k: unsure 🔍 -3% - +2% (-1.52ms - +1.15ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -0% - +1% (-0.05ms - +0.23ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -2% - +1% (-1.80ms - +1.18ms)
    preact-local vs preact-main
  • text-update: unsure 🔍 -6% - +4% (-0.11ms - +0.08ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -2% - +1% (-0.58ms - +0.25ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -5% - +3% (-1.61ms - +1.01ms)
    preact-local vs preact-main

usedJSHeapSize

  • create10k: unsure 🔍 -0% - -0% (-0.00ms - -0.00ms)
    preact-local vs preact-main
  • filter-list: unsure 🔍 -0% - +0% (-0.00ms - +0.00ms)
    preact-local vs preact-main
  • hydrate1k: unsure 🔍 -5% - +4% (-0.24ms - +0.23ms)
    preact-local vs preact-main
  • many-updates: unsure 🔍 -0% - -0% (-0.00ms - -0.00ms)
    preact-local vs preact-main
  • replace1k: unsure 🔍 -0% - -0% (-0.00ms - -0.00ms)
    preact-local vs preact-main
  • text-update: unsure 🔍 -1% - +5% (-0.01ms - +0.05ms)
    preact-local vs preact-main
  • todo: unsure 🔍 -0% - -0% (-0.00ms - -0.00ms)
    preact-local vs preact-main
  • update10th1k: unsure 🔍 -0% - +0% (-0.01ms - +0.01ms)
    preact-local vs preact-main

Results

create10k

duration

VersionAvg timevs preact-localvs preact-main
preact-local542.13ms - 550.33ms-unsure 🔍
-1% - +1%
-6.43ms - +6.32ms
preact-main541.40ms - 551.17msunsure 🔍
-1% - +1%
-6.32ms - +6.43ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local19.07ms - 19.07ms-unsure 🔍
-0% - -0%
-0.00ms - -0.00ms
preact-main19.07ms - 19.07msunsure 🔍
+0% - +0%
+0.00ms - +0.00ms
-
filter-list

duration

VersionAvg timevs preact-localvs preact-main
preact-local16.51ms - 16.67ms-unsure 🔍
-1% - +1%
-0.21ms - +0.14ms
preact-main16.47ms - 16.79msunsure 🔍
-1% - +1%
-0.14ms - +0.21ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.55ms - 1.56ms-unsure 🔍
-0% - +0%
-0.00ms - +0.00ms
preact-main1.55ms - 1.56msunsure 🔍
-0% - +0%
-0.00ms - +0.00ms
-
hydrate1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local57.86ms - 59.76ms-unsure 🔍
-3% - +2%
-1.52ms - +1.15ms
preact-main58.05ms - 59.94msunsure 🔍
-2% - +3%
-1.15ms - +1.52ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local5.03ms - 5.39ms-unsure 🔍
-5% - +4%
-0.24ms - +0.23ms
preact-main5.06ms - 5.36msunsure 🔍
-4% - +5%
-0.23ms - +0.24ms
-
many-updates

duration

VersionAvg timevs preact-localvs preact-main
preact-local16.47ms - 16.75ms-unsure 🔍
-0% - +1%
-0.05ms - +0.23ms
preact-main16.48ms - 16.55msunsure 🔍
-1% - +0%
-0.23ms - +0.05ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.74ms - 3.74ms-unsure 🔍
-0% - -0%
-0.00ms - -0.00ms
preact-main3.74ms - 3.74msunsure 🔍
+0% - +0%
+0.00ms - +0.00ms
-
replace1k
  • Browser: chrome-headless
  • Sample size: 100
  • Built by: CI #5916
  • Commit: e36a91d

duration

VersionAvg timevs preact-localvs preact-main
preact-local86.33ms - 88.55ms-unsure 🔍
-2% - +1%
-1.80ms - +1.18ms
preact-main86.76ms - 88.75msunsure 🔍
-1% - +2%
-1.18ms - +1.80ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local3.01ms - 3.01ms-unsure 🔍
-0% - -0%
-0.00ms - -0.00ms
preact-main3.01ms - 3.01msunsure 🔍
+0% - +0%
+0.00ms - +0.00ms
-

run-warmup-0

VersionAvg timevs preact-localvs preact-main
preact-local27.88ms - 28.85ms-unsure 🔍
-3% - +2%
-0.73ms - +0.60ms
preact-main27.97ms - 28.89msunsure 🔍
-2% - +3%
-0.60ms - +0.73ms
-

run-warmup-1

VersionAvg timevs preact-localvs preact-main
preact-local32.86ms - 34.45ms-unsure 🔍
-3% - +3%
-0.96ms - +1.12ms
preact-main32.90ms - 34.25msunsure 🔍
-3% - +3%
-1.12ms - +0.96ms
-

run-warmup-2

VersionAvg timevs preact-localvs preact-main
preact-local32.09ms - 34.02ms-unsure 🔍
-4% - +3%
-1.39ms - +1.14ms
preact-main32.37ms - 33.99msunsure 🔍
-3% - +4%
-1.14ms - +1.39ms
-

run-warmup-3

VersionAvg timevs preact-localvs preact-main
preact-local29.77ms - 30.81ms-unsure 🔍
-3% - +1%
-1.04ms - +0.40ms
preact-main30.11ms - 31.11msunsure 🔍
-1% - +3%
-0.40ms - +1.04ms
-

run-warmup-4

VersionAvg timevs preact-localvs preact-main
preact-local20.89ms - 21.24ms-unsure 🔍
-0% - +2%
-0.09ms - +0.39ms
preact-main20.75ms - 21.07msunsure 🔍
-2% - +0%
-0.39ms - +0.09ms
-

run-final

VersionAvg timevs preact-localvs preact-main
preact-local27.72ms - 28.39ms-unsure 🔍
-0% - +3%
-0.07ms - +0.73ms
preact-main27.51ms - 27.94msunsure 🔍
-3% - +0%
-0.73ms - +0.07ms
-
text-update
  • Browser: chrome-headless
  • Sample size: 210
  • Built by: CI #5916
  • Commit: e36a91d

duration

VersionAvg timevs preact-localvs preact-main
preact-local1.81ms - 1.94ms-unsure 🔍
-6% - +4%
-0.11ms - +0.08ms
preact-main1.81ms - 1.95msunsure 🔍
-4% - +6%
-0.08ms - +0.11ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.01ms - 1.06ms-unsure 🔍
-1% - +5%
-0.01ms - +0.05ms
preact-main1.00ms - 1.03msunsure 🔍
-5% - +1%
-0.05ms - +0.01ms
-
todo

duration

VersionAvg timevs preact-localvs preact-main
preact-local31.75ms - 32.17ms-unsure 🔍
-2% - +1%
-0.58ms - +0.25ms
preact-main31.77ms - 32.48msunsure 🔍
-1% - +2%
-0.25ms - +0.58ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local1.26ms - 1.26ms-unsure 🔍
-0% - -0%
-0.00ms - -0.00ms
preact-main1.27ms - 1.27msunsure 🔍
+0% - +0%
+0.00ms - +0.00ms
-
update10th1k

duration

VersionAvg timevs preact-localvs preact-main
preact-local32.71ms - 34.45ms-unsure 🔍
-5% - +3%
-1.61ms - +1.01ms
preact-main32.91ms - 34.86msunsure 🔍
-3% - +5%
-1.01ms - +1.61ms
-

usedJSHeapSize

VersionAvg timevs preact-localvs preact-main
preact-local2.97ms - 2.98ms-unsure 🔍
-0% - +0%
-0.01ms - +0.01ms
preact-main2.97ms - 2.99msunsure 🔍
-0% - +0%
-0.01ms - +0.01ms
-

tachometer-reporter-action v2 for CI

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Size Change: +7 B (+0.04%)

Total Size: 15.9 kB

📦 View Changed
Filename Size Change
dist/preact.mjs 4.9 kB +7 B (+0.14%)
ℹ️ View Unchanged
Filename Size
compat/dist/compat.mjs 3.92 kB
debug/dist/debug.mjs 3.88 kB
devtools/dist/devtools.mjs 273 B
hooks/dist/hooks.mjs 1.58 kB
jsx-runtime/dist/jsxRuntime.mjs 868 B
test-utils/dist/testUtils.mjs 473 B

compressed-size-action

@coveralls

coveralls commented Sep 2, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 99.856%. remained the same — JoviDeCroock/extract-cold-diff-paths into main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants