Skip to content

Add trace spans for turbopack persistence in .next/trace#90397

Merged
lukesandberg merged 4 commits intocanaryfrom
trace_persisting
Mar 5, 2026
Merged

Add trace spans for turbopack persistence in .next/trace#90397
lukesandberg merged 4 commits intocanaryfrom
trace_persisting

Conversation

@lukesandberg
Copy link
Contributor

@lukesandberg lukesandberg commented Feb 23, 2026

Summary

  • Add a generic TraceEvent compilation event type that carries a name, wall-clock timing, and arbitrary attributes
  • Emit TraceEvent from Turbopack's Rust backend for cache persistence and compaction operations
  • Expose eventJson on compilation events through the NAPI bridge
  • Record turbopack-persistence and turbopack-compaction trace spans in .next/trace with memory usage snapshots, in both dev and build workflows

Details

Turbopack persistence and compaction operations were invisible in .next/trace. The only signal was a console log for operations exceeding 10s.

A new generic TraceEvent type replaces the need for per-operation event structs. It carries a name, start/end wall-clock timestamps, and a Vec of key-value attributes. On the JS side, backgroundLogCompilationEvents handles all TraceEvents with a single code path — creating trace spans via manualTraceChild and recording memory usage snapshots. Adding new traced operations requires only a few lines of Rust and zero JS changes.

At @bgw's suggestion, I considered integrating as a tracing_subscriber::Layer to automatically forward spans to the compilation event system, but this ended up requiring quite a bit of code (a new subscriber, 'target' impl, span lifecycle management, new crate dependencies) for what is currently just 2 events, and we don't really anticipate adding more.

Test plan

  • Integration test in test/e2e/filesystem-cache verifying turbopack-persistence spans exist with correct attributes
  • pnpm test-dev-turbo test/e2e/filesystem-cache
  • pnpm test-start-turbo test/e2e/filesystem-cache

@nextjs-bot nextjs-bot added created-by: Turbopack team PRs by the Turbopack team. Turbopack Related to Turbopack with Next.js. type: next labels Feb 23, 2026
Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@nextjs-bot
Copy link
Collaborator

nextjs-bot commented Feb 24, 2026

Tests Passed

@nextjs-bot
Copy link
Collaborator

nextjs-bot commented Feb 24, 2026

Stats from current PR

✅ No significant changes detected

📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 455ms 454ms ▁▇▁▁█
Cold (Ready in log) 439ms 438ms ▁▆▁▁█
Cold (First Request) 1.236s 1.235s ▃▆▁▃█
Warm (Listen) 456ms 456ms ▁▇▁▁█
Warm (Ready in log) 444ms 441ms ▁▇▁▁█
Warm (First Request) 347ms 351ms ▁▆▁▂█
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 456ms 456ms ▁▁▁▁▁
Cold (Ready in log) 436ms 435ms ▃▃▄▂▁
Cold (First Request) 1.940s 1.928s ▁▁▂▁▁
Warm (Listen) 456ms 457ms ▁▁▁▁▁
Warm (Ready in log) 437ms 436ms ▃▂▃▂▁
Warm (First Request) 1.933s 1.952s ▁▁▂▁▁

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 3.912s 3.919s ▁▆▁▁█
Cached Build 3.947s 3.894s ▁▆▁▁█
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 14.020s 13.997s ▁▁▂▁▁
Cached Build 14.023s 14.068s ▁▁▂▁▁
node_modules Size 475 MB 475 MB ▁▁▁▁▁
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles: **401 kB** → **401 kB** ✅ -31 B

80 files with content-based hashes (individual files not comparable between builds)

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 767 B 760 B
Total 767 B 760 B ✅ -7 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 451 B 451 B
Total 451 B 451 B

📦 Webpack

Client

Main Bundles
Canary PR Change
5528-HASH.js gzip 5.54 kB N/A -
6280-HASH.js gzip 59.4 kB N/A -
6335.HASH.js gzip 169 B N/A -
912-HASH.js gzip 4.59 kB N/A -
e8aec2e4-HASH.js gzip 62.6 kB N/A -
framework-HASH.js gzip 59.7 kB 59.7 kB
main-app-HASH.js gzip 256 B 254 B
main-HASH.js gzip 39.1 kB 39.1 kB
webpack-HASH.js gzip 1.68 kB 1.68 kB
262-HASH.js gzip N/A 4.59 kB -
2889.HASH.js gzip N/A 169 B -
5602-HASH.js gzip N/A 5.55 kB -
6948ada0-HASH.js gzip N/A 62.6 kB -
9544-HASH.js gzip N/A 60.2 kB -
Total 233 kB 234 kB ⚠️ +732 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 194 B 194 B
_error-HASH.js gzip 183 B 180 B 🟢 3 B (-2%)
css-HASH.js gzip 331 B 330 B
dynamic-HASH.js gzip 1.81 kB 1.81 kB
edge-ssr-HASH.js gzip 256 B 256 B
head-HASH.js gzip 351 B 352 B
hooks-HASH.js gzip 384 B 383 B
image-HASH.js gzip 580 B 581 B
index-HASH.js gzip 260 B 260 B
link-HASH.js gzip 2.51 kB 2.51 kB
routerDirect..HASH.js gzip 320 B 319 B
script-HASH.js gzip 386 B 386 B
withRouter-HASH.js gzip 315 B 315 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.98 kB 7.98 kB ✅ -1 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 125 kB 125 kB
page.js gzip 254 kB 254 kB
Total 378 kB 379 kB ⚠️ +528 B
Middleware
Canary PR Change
middleware-b..fest.js gzip 617 B 619 B
middleware-r..fest.js gzip 156 B 155 B
middleware.js gzip 43.6 kB 43.5 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 45.2 kB 45.1 kB ✅ -113 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 715 B 718 B
Total 715 B 718 B ⚠️ +3 B
Build Cache
Canary PR Change
0.pack gzip 4.03 MB 4.04 MB 🔴 +10.3 kB (+0%)
index.pack gzip 103 kB 101 kB 🟢 1.43 kB (-1%)
index.pack.old gzip 102 kB 102 kB
Total 4.24 MB 4.25 MB ⚠️ +8.3 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 321 kB 321 kB
app-page-exp..prod.js gzip 170 kB 170 kB
app-page-tur...dev.js gzip 321 kB 321 kB
app-page-tur..prod.js gzip 170 kB 170 kB
app-page-tur...dev.js gzip 318 kB 318 kB
app-page-tur..prod.js gzip 168 kB 168 kB
app-page.run...dev.js gzip 318 kB 318 kB
app-page.run..prod.js gzip 168 kB 168 kB
app-route-ex...dev.js gzip 70.3 kB 70.3 kB
app-route-ex..prod.js gzip 48.6 kB 48.6 kB
app-route-tu...dev.js gzip 70.4 kB 70.4 kB
app-route-tu..prod.js gzip 48.7 kB 48.7 kB
app-route-tu...dev.js gzip 69.9 kB 69.9 kB
app-route-tu..prod.js gzip 48.4 kB 48.4 kB
app-route.ru...dev.js gzip 69.9 kB 69.9 kB
app-route.ru..prod.js gzip 48.4 kB 48.4 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 43.2 kB 43.2 kB
pages-api-tu..prod.js gzip 32.9 kB 32.9 kB
pages-api.ru...dev.js gzip 43.2 kB 43.2 kB
pages-api.ru..prod.js gzip 32.9 kB 32.9 kB
pages-turbo....dev.js gzip 52.6 kB 52.6 kB
pages-turbo...prod.js gzip 38.5 kB 38.5 kB
pages.runtim...dev.js gzip 52.6 kB 52.6 kB
pages.runtim..prod.js gzip 38.5 kB 38.5 kB
server.runti..prod.js gzip 61.8 kB 61.8 kB
Total 2.83 MB 2.83 MB
📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/e19727d23e8c60bda065cdde08a83d4dfabb9088/next

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 24, 2026

Merging this PR will degrade performance by 3.48%

❌ 1 regressed benchmark
✅ 16 untouched benchmarks
⏩ 3 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation packages-bundle.js[full] 1.2 s 1.2 s -3.48%

Comparing trace_persisting (e19727d) with canary (1c9577e)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

}

// Record TraceEvent compilation events as trace spans in .next/trace.
if (parentSpan && event.typeName === 'TraceEvent' && event.eventJson) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ideally eventJson would also be a napi_object so we could get types generated

Copy link
Member

Choose a reason for hiding this comment

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

@bgw would this be easier in v3 of the napi crate?

Copy link
Member

Choose a reason for hiding this comment

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

I think this is a crate hierarchy problem, not really a napi problem. TraceEvent is defined in turbo-tasks, but we don't want that crate to depend on napi.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

correct, i would need to create a dual set of types in the next crate that is emitting these events and then we could get types..

this works but is officially lame

@lukesandberg lukesandberg force-pushed the trace_persisting branch 2 times, most recently from 0642539 to 733a839 Compare February 24, 2026 16:30
@lukesandberg lukesandberg marked this pull request as ready for review February 26, 2026 01:07
@lukesandberg lukesandberg changed the title Add trace spans for turbopack persistence in next Add trace spans for turbopack persistence in .next/trace Feb 26, 2026
Copy link
Member

@wbinnssmith wbinnssmith left a comment

Choose a reason for hiding this comment

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

lgtm. thanks for cleaning up the reporters!

@lukesandberg lukesandberg merged commit 286a73f into canary Mar 5, 2026
289 of 292 checks passed
Copy link
Contributor Author

Merge activity

@lukesandberg lukesandberg deleted the trace_persisting branch March 5, 2026 00:33
sokra pushed a commit that referenced this pull request Mar 6, 2026
## Summary

- Add a generic `TraceEvent` compilation event type that carries a name, wall-clock timing, and arbitrary attributes
- Emit `TraceEvent` from Turbopack's Rust backend for cache persistence and compaction operations
- Expose `eventJson` on compilation events through the NAPI bridge
- Record `turbopack-persistence` and `turbopack-compaction` trace spans in `.next/trace` with memory usage snapshots, in both dev and build workflows

## Details

Turbopack persistence and compaction operations were invisible in `.next/trace`. The only signal was a console log for operations exceeding 10s.

A new generic `TraceEvent` type replaces the need for per-operation event structs. It carries a name, start/end wall-clock timestamps, and a `Vec` of key-value attributes. On the JS side, `backgroundLogCompilationEvents` handles all `TraceEvent`s with a single code path — creating trace spans via `manualTraceChild` and recording memory usage snapshots. Adding new traced operations requires only a few lines of Rust and zero JS changes.

At @bgw's suggestion, I considered integrating as a `tracing_subscriber::Layer` to automatically forward spans to the compilation event system, but this ended up requiring quite a bit of code (a new subscriber, 'target' impl, span lifecycle management, new crate dependencies) for what is currently just 2 events, and we don't really anticipate adding more.

## Test plan

- [x] Integration test in `test/e2e/filesystem-cache` verifying `turbopack-persistence` spans exist with correct attributes
- [x] `pnpm test-dev-turbo test/e2e/filesystem-cache`
- [x] `pnpm test-start-turbo test/e2e/filesystem-cache`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by: Turbopack team PRs by the Turbopack team. tests Turbopack Related to Turbopack with Next.js. type: next

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants