Skip to content

fix(pack): preserve updates during HMR subscription setup - #3304

Merged
fireairforce merged 4 commits into
nextfrom
zoomdong/fix-hmr-initial-subscription-race
Aug 14, 2026
Merged

fix(pack): preserve updates during HMR subscription setup#3304
fireairforce merged 4 commits into
nextfrom
zoomdong/fix-hmr-initial-subscription-race

Conversation

@fireairforce

@fireairforce fireairforce commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

Fix an HMR race where a source edit made between page load and subscription setup was treated as the initial computation and never reached the browser.

  • embed the dev chunk-list version in Turbopack subscribe messages
  • compare that version with the native HMR baseline and restart only stale clients
  • forward non-issue initial subscription results instead of unconditionally swallowing them
  • add unit coverage and update the affected development protocol snapshots

Test Plan

  • npm run vitest:all (46 Pack tests and 6 Pack Shared tests)
  • cargo clippy --all-targets -- -D warnings --no-deps
  • cargo fmt and targeted Biome/Prettier checks
  • run all 127 Pack snapshot tests with cargo test -p pack-tests -- --ignored
  • reproduce the missed first update with @utoo/pack@1.5.5 in the 19-page EVJS jinni-explore app, then inject this branch and verify the same cold-start edit updates in 769 ms with one total main-frame navigation and no page errors

Copy link
Copy Markdown
Member Author

Turbopack-side changes have been split into a standalone draft PR: utooland/next.js#182

This PR keeps the Utoo protocol/NAPI integration and points the submodule at those Turbopack commits.

@fireairforce
fireairforce marked this pull request as ready for review August 14, 2026 07:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6563b825c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/pack/src/core/hmr.ts Outdated
@github-actions

Copy link
Copy Markdown

📊 Performance Benchmark Report (with-antd)

Utoopack Performance Report

Report ID: utoopack_performance_report_20260814_074208
Generated: 2026-08-14 07:42:08
Trace File: trace_antd.json (0.4GB, 1.13M spans)
Test Project: examples/with-antd


Executive Summary

Metric Value Assessment
Total Wall Time 7,041.2 ms Baseline
Total Thread Work (de-duped) 20,712.4 ms Non-overlapping busy time
Effective Parallelism 2.9x thread_work / wall_time
Working Threads 9 Threads with actual spans
Thread Utilization 32.7% ⚠️ Suboptimal
Total Spans 1,128,118 All B/E + X events
Meaningful Spans (>= 10us) 354,513 (31.4% of total)
Tracing Noise (< 10us) 773,605 (68.6% of total)

Build Phase Timeline

Shows when each build phase is active and how much CPU it consumes.
Self-Time is the time spent exclusively in that phase (excluding children).

Phase Spans Inclusive (ms) Self-Time (ms) Wall Range (ms)
Resolve 92,809 2,489.4 1,930.3 3,614.2
Parse 10,046 1,134.5 1,079.9 6,376.3
Analyze 227,171 12,157.6 8,572.4 6,268.0
Chunk 8,398 2,914.4 809.1 2,416.6
Codegen 10,466 1,497.1 1,420.3 2,074.1
Emit 34 41.4 20.7 12.8
Other 5,589 6,760.0 4,053.3 7,041.2

Workload Distribution by Diagnostic Tier

Category Spans Inclusive (ms) % Work Self-Time (ms) % Self
P0: Scheduling & Resolution 322,476 15,042.4 72.6% 10,760.6 52.0%
P1: I/O & Heavy Tasks 2,901 103.2 0.5% 82.5 0.4%
P2: Architecture (Locks/Memory) 1 0.0 0.0% 0.0 0.0%
P3: Asset Pipeline 27,413 5,576.0 26.9% 3,339.3 16.1%
P4: Bridge/Interop 0 0.0 0.0% 0.0 0.0%
Other 1,722 6,272.9 30.3% 3,703.7 17.9%

Top 20 Tasks by Self-Time

Self-time is the exclusive duration: time spent in the task itself, not in sub-tasks.
This is the most accurate indicator of where CPU cycles are actually spent.

Self (ms) Inclusive (ms) Count Avg Self (us) P95 Self (ms) Max Self (ms) % Work Task Name Top Caller
4,602.9 6,523.8 145,225 31.7 0.1 14.0 22.2% module write all entrypoints to disk (1%)
2,400.3 2,613.1 25 96013.3 407.8 459.9 11.6% save snapshot persist (4%)
1,928.5 2,032.5 25,741 74.9 0.2 188.2 9.3% analyze ecmascript module module (66%)
1,261.3 1,365.3 51,746 24.4 0.0 8.0 6.1% internal resolving resolving (29%)
1,142.3 2,676.0 47,419 24.1 0.0 8.5 5.5% process module module (20%)
1,025.8 1,080.4 7,878 130.2 0.5 90.4 5.0% parse ecmascript process module (25%)
789.9 789.9 8,043 98.2 0.4 7.1 3.8% precompute code generation generate merged code (51%)
755.0 755.0 5,927 127.4 0.4 111.9 3.6% compute async module info compute merged modules (0%)
689.4 2,053.7 1,422 484.8 1.3 253.5 3.3% generate merged code chunking (66%)
661.3 1,116.5 40,364 16.4 0.0 8.8 3.2% resolving module (31%)
645.4 2,748.9 6,750 95.6 0.1 44.9 3.1% chunking compute async chunks (0%)
404.5 404.5 329 1229.6 1.0 254.0 2.0% generate source map code generation (83%)
368.1 727.2 173 2127.9 4.6 200.6 1.8% emit code generate merged code (32%)
292.7 423.3 3,468 84.4 0.0 140.0 1.4% write all entrypoints to disk None (0%)
225.9 302.7 2,094 107.9 0.2 70.6 1.1% code generation chunking (12%)
221.4 221.4 16 13837.9 73.1 97.5 1.1% blocking save snapshot (62%)
158.8 160.5 1,554 102.2 0.1 30.2 0.8% compute async chunks write all entrypoints to disk (0%)
84.1 84.1 671 125.3 0.0 24.0 0.4% compute binding usage info write all entrypoints to disk (1%)
57.0 63.9 398 143.1 0.1 11.5 0.3% async reference write all entrypoints to disk (1%)
54.1 54.1 2,166 25.0 0.0 1.0 0.3% read file parse ecmascript (91%)

Critical Path Analysis

The longest sequential dependency chains that determine wall-clock time.
Focus on reducing the depth of these chains to improve parallelism.

Rank Self-Time (ms) Depth Path
1 557.4 3 persist → save snapshot → blocking
2 454.1 3 chunking → generate merged code → emit code
3 413.6 2 save snapshot → blocking
4 304.1 4 chunking → generate merged code → emit code → generate source map
5 188.2 2 process module → analyze ecmascript module

Batching Candidates

High-volume tasks dominated by a single parent. If the parent can batch them,
it drastically reduces scheduler overhead.

Task Name Count Top Caller (Attribution) Avg Self P95 Self Total Self
No obvious batching candidates found - - - - -

Duration Distribution

Range Count Percentage
<10us 773,605 68.6%
10us-100us 335,897 29.8%
100us-1ms 15,455 1.4%
1ms-10ms 3,037 0.3%
10ms-100ms 104 0.0%
>100ms 20 0.0%

Action Items

  1. [P0] Focus on tasks with the highest Self-Time — these are where CPU cycles are actually spent.
  2. [P0] Use Batching Candidates to identify callers that should use try_join or reduce #[turbo_tasks::function] granularity.
  3. [P1] Check Build Phase Timeline for phases with disproportionate wall range vs. self-time (= serialization).
  4. [P1] Inspect P95 Self (ms) for heavy monolith tasks. Focus on long-tail outliers, not averages.
  5. [P1] Review Critical Paths — reducing the longest chain depth directly improves wall-clock time.
  6. [P2] If Thread Utilization < 60%, investigate scheduling gaps (lock contention or deep dependency chains).

Report generated by Utoopack Performance Analysis Agent

@fireairforce
fireairforce enabled auto-merge (squash) August 14, 2026 07:43
@fireairforce
fireairforce merged commit 1165169 into next Aug 14, 2026
35 checks passed
@fireairforce
fireairforce deleted the zoomdong/fix-hmr-initial-subscription-race branch August 14, 2026 07:57
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.

2 participants