Skip to content

perf(benchmark): enable pureFunctions for production bundle benches#14558

Draft
hardfist wants to merge 2 commits into
mainfrom
codex/bench-pure-functions-default
Draft

perf(benchmark): enable pureFunctions for production bundle benches#14558
hardfist wants to merge 2 commits into
mainfrom
codex/bench-pure-functions-default

Conversation

@hardfist

Copy link
Copy Markdown
Contributor

Summary

  • add an ExperimentsBuilder::pure_functions setter on the Rust builder side
  • enable pure_functions explicitly for production sourcemap bundle benchmarks
  • add a focused builder test that locks pure_functions defaults to production/undefined mode, matching the JS default behavior

Validation

  • cargo fmt -p rspack -p rspack_benchmark
  • pnpm run build:binding:dev

cargo test -p rspack pure_functions_defaults_follow_mode and cargo check -p rspack_benchmark --benches were started after rebasing onto latest origin/main, then stopped when requested to open the draft PR directly.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

📦 Binary Size-limit

Comparing 441a757 to chore: release version 2.1.0-rc.0 (#14546) by harpsealjs

❌ Size increased by 4.00KB from 67.73MB to 67.74MB (⬆️0.01%)

@codspeed-hq

codspeed-hq Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will improve performance by 6.77%

⚡ 2 improved benchmarks
✅ 39 untouched benchmarks
⏩ 47 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation rust@create_named_chunk_ids 3 ms 2.8 ms +6.82%
Simulation rust@create_chunk_ids 3.2 ms 3 ms +6.72%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing codex/bench-pure-functions-default (441a757) with main (7d8e6e4)

Open in CodSpeed

Footnotes

  1. 47 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.

@hardfist

Copy link
Copy Markdown
Contributor Author

@codspeed explain why threejs production no change

@codspeed-hq

codspeed-hq Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

@codspeed explain why threejs production no change

Why the threejs production benchmark shows no change

Short answer: explicitly enabling pure_functions in the production benchmark is a no-op, because pure_functions already defaults to true in production mode. So the compiler options — and therefore the work measured — are identical before and after this PR.

The trace:

In this PR the production benchmark variant sets it explicitly (xtask/benchmark/benches/groups/bundle/util.rs):

builder.mode(Mode::Production);
builder.devtool(rspack::builder::Devtool::SourceMap);
builder.experiments(Experiments::builder().css(true).pure_functions(true));

But the builder already derives the default from the mode (crates/rspack/src/builder/mod.rs):

pure_functions: d!(self.pure_functions, _production),

where d!(o, v) = o.unwrap_or(v) and _production is true whenever the mode is Production (or unset). So an unset pure_functions already resolves to true in production. Setting it explicitly to true resolves to the exact same value.

That's exactly the behavior the new pure_functions_defaults_follow_mode test locks in — and it's also why CodSpeed reports no change: the resolved CompilerOptions are byte-for-byte equivalent, so there's no extra (or different) work to measure. The same reasoning applies to every *-production-sourcemap variant, not just threejs.

Takeaways:

  • The change is a correctness/explicitness improvement (it pins intent against future default drift), not a performance change — a flat result is the expected outcome.
  • To actually move this benchmark you'd need to measure the delta of the flag, e.g. compare a pure_functions(false) production variant against the default — that would isolate the cost/benefit of the pure-call tree-shaking analysis. As-is, both sides of the comparison already have it on.
Summary
  • Warming up the performance wizard...
  • Handling comment — Comment handling finished successfully

Was this response helpful? React with 👍 or 👎 to help us improve CodSpeedBot.

@CPunisher

Copy link
Copy Markdown
Contributor

@codspeed explain why bundle@basic-react-production-sourcemap and bundle@threejs-production-sourcemap are faster

@codspeed-hq

codspeed-hq Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

@codspeed explain why bundle@basic-react-production-sourcemap and bundle@threejs-production-sourcemap are faster

Why bundle@basic-react-production-sourcemap and bundle@threejs-production-sourcemap are not actually faster

Short answer: they aren't. In every comparison I ran, both of those bundle benchmarks land in the unchanged bucket — not the improved one.

The CodSpeed report flags only two benchmarks as faster, and neither is a bundle case:

Benchmark Base Head Change
rust@create_named_chunk_ids 3 ms 2.8 ms +6.82%
rust@create_chunk_ids 3.2 ms 3 ms +6.72%

bundle@basic-react-production-sourcemap (~142 ms) and bundle@threejs-production-sourcemap (~192 ms) both register as unchanged.

Why the bundle benches don't move

This is consistent with the earlier explanation for threejs: toggling pure_functions on these production variants is effectively a no-op for the work being measured. pure_functions already defaults to true in production mode, so enabling it explicitly resolves to the identical CompilerOptions. I also compared the enable commit against the newer chore: disable pure function commit directly, and the bundle benchmarks still don't move — so even flipping the flag has no measurable cost/benefit on these fixtures. A flat result is the expected outcome.

Why the two chunk-id benchmarks "improved"

That +6.7% is almost certainly run-to-run jitter, not a real speedup:

  • create_chunk_ids / create_named_chunk_ids are among the shortest simulation benchmarks (~3 ms). Their hot path lives entirely in rspack_ids and rspack_core chunk-graph code, and leans heavily on rayon parallel iterators — so sub-~7% swings are typical noise.
  • This PR only touches the benchmark harness (pure_functions setters/tests) — it doesn't change any chunk-id or chunk-graph code, so there's no mechanism for it to speed up these stages.
  • The same ~6.7% delta shows up whether I compare against main or against the PR's own earlier commit, which is the signature of variance on these noise-prone benches rather than a change introduced by the PR.

Takeaway: the production-sourcemap bundle benches are correctly reported as flat, and the chunk-id "improvement" is noise. If you want to actually measure the impact of pure_functions, you'd need a dedicated variant comparing pure_functions(false) against the production default to isolate the cost of the pure-call tree-shaking analysis.

Summary
  • Warming up the performance wizard...
  • Investigating benchmark changes — Confirmed the production-sourcemap bundle benchmarks are unchanged; only noise-prone chunk-id stage benchmarks moved
  • Handling comment — Comment handling finished successfully

Was this response helpful? React with 👍 or 👎 to help us improve CodSpeedBot.

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