Skip to content

Perf: Fast path for trace() when opentelemetry is not enabled#92678

Merged
timneutkens merged 1 commit into
canaryfrom
03-13-perf_only_instrument_clientcomponentloadtimes_when_used
Apr 15, 2026
Merged

Perf: Fast path for trace() when opentelemetry is not enabled#92678
timneutkens merged 1 commit into
canaryfrom
03-13-perf_only_instrument_clientcomponentloadtimes_when_used

Conversation

@timneutkens
Copy link
Copy Markdown
Contributor

@timneutkens timneutkens commented Apr 12, 2026

What?

Skip the tracer.trace() instrumentation path when OpenTelemetry tracing is not actually enabled.

Why?

trace() is used in hot paths, and even with tracing disabled it was still doing option coercion, context lookups, span bookkeeping, and context.with(...) setup. That adds avoidable overhead for the default no-op tracing case.

How?

  • add an isTracingEnabled() check that treats an active recording span as enabled
  • detect the default ProxyTracerProvider -> NoopTracerProvider setup and treat it as tracing disabled
  • bail out of trace() before any span or context work when neither tracing nor performance logging is enabled

Benchmark

Setup

  • Scenario: e2e (next build + next start, Turbopack)
  • Stream mode: node
  • Route: / (lightest route, most sensitive to per-request overhead)
  • Serial requests: 500, load requests: 5000, load concurrency: 80

Single-client (req/s)

Run 1 Run 2 Run 3 Avg
Canary 743 755 789 762
PR #92678 785 787 837 803
Delta +5.4%

Under-load (req/s)

Run 1 Run 2 Run 3 Avg
Canary 1689 1768 1852 1770
PR #92678 1799 1926 1767 1831
Delta +3.4%

Conclusion

The PR shows a consistent ~5% req/s improvement on single-client / across 3 runs, where the tracer overhead is proportionally largest relative to render time. Streaming-heavy routes are unaffected since render time dominates. Under-load shows a smaller +3.4% improvement with more variance.

Copy link
Copy Markdown
Contributor Author

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

@timneutkens timneutkens changed the title Perf: Only instrument clientComponentLoadTimes when used Perf: Don't instrument Apr 12, 2026
@timneutkens timneutkens changed the title Perf: Don't instrument Perf: Fast path for trace() when opentelemetry is not enabled Apr 12, 2026
@timneutkens timneutkens marked this pull request as ready for review April 12, 2026 11:28
@timneutkens timneutkens requested a review from gnoff April 12, 2026 11:32
@nextjs-bot
Copy link
Copy Markdown
Contributor

nextjs-bot commented Apr 12, 2026

Tests Passed

timneutkens added a commit that referenced this pull request Apr 13, 2026
## What

Adds a new "A/B branch comparison" section to `bench/BENCHMARKING.md`
with practical guidance for comparing benchmark results across two
branches.

## Why

From running benchmarks comparing canary vs PR #92678, we identified
several patterns that lead to noisy or misleading results:

- Running the full route suite when only one route shows signal wastes
time (~3 min per run)
- The default 120 serial requests is too noisy for sub-2ms routes
- Single runs can swing 10-15% on light routes
- Percentage deltas from a single pair of runs can be misleading without
absolute numbers

## What's in the new section

- Start with a focused route, not the full suite
- Increase request counts for fast routes (500 serial / 5000 load)
- Run at least 3 times per side to average out noise
- Compare absolute req/s, not just deltas
- Watch for system state drift between runs
- Full example workflow with checkout/build/run loop

<!-- NEXT_JS_LLM_PR -->
@timneutkens timneutkens merged commit 8cbab6e into canary Apr 15, 2026
337 of 340 checks passed
@timneutkens timneutkens deleted the 03-13-perf_only_instrument_clientcomponentloadtimes_when_used branch April 15, 2026 13:12
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants