turbopack: gate ValueDebugFormat and ValueDebug behind debug_assertions#92628
turbopack: gate ValueDebugFormat and ValueDebug behind debug_assertions#92628
Conversation
Tests Passed |
Stats from current PR🟢 1 improvement
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (25 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsfailed to diffapp-page.runtime.dev.jsfailed to diffapp-page.runtime.prod.jsfailed to diffapp-route-ex..ntime.dev.jsDiff too large to display app-route-ex..time.prod.jsDiff too large to display app-route-tu..ntime.dev.jsDiff too large to display app-route-tu..time.prod.jsDiff too large to display app-route-tu..ntime.dev.jsDiff too large to display app-route-tu..time.prod.jsDiff too large to display app-route.runtime.dev.jsDiff too large to display app-route.ru..time.prod.jsDiff too large to display pages-api-tu..ntime.dev.jsDiff too large to display pages-api-tu..time.prod.jsDiff too large to display pages-api.runtime.dev.jsDiff too large to display pages-api.ru..time.prod.jsDiff too large to display pages-turbo...ntime.dev.jsDiff too large to display pages-turbo...time.prod.jsDiff too large to display pages.runtime.dev.jsDiff too large to display pages.runtime.prod.jsDiff too large to display server.runtime.prod.jsDiff too large to display 📎 Tarball URL |
Merging this PR will degrade performance by 3.53%
Performance Changes
Comparing Footnotes
|
The ValueDebugFormat trait method, ValueDebugFormatString enum, and all related impl blocks (for Vc, ResolvedVc, ReadRef, MappedReadRef, AliasMap, and all std/auto_hash_map/smallvec/FxIndex* types) are now compiled only in debug builds. In release builds the derive macros emit empty ValueDebugFormat impls (no method) and lightweight ValueDebug impls that return the type name only, eliminating ~2.1% of binary size from the formatting machinery. Co-Authored-By: Claude <noreply@anthropic.com>
d16dabb to
ba057ba
Compare
Instead of emitting a lightweight no-op ValueDebug impl for each type in release builds, replace the value_trait definition itself with an empty marker trait + blanket impl in release builds. This means no per-type ValueDebug registration code is generated at all in release builds. Co-Authored-By: Claude <noreply@anthropic.com>
- Move all `#[cfg(debug_assertions)]`-gated items into a single `detail` module so the gate is declared once instead of on every item - Use `futures::future::BoxFuture` for the `Async` variant of `ValueDebugFormatString` instead of the verbose inline type Co-Authored-By: Claude <noreply@anthropic.com>
What?
Gate
ValueDebugFormatandValueDebugbehind#[cfg(debug_assertions)]across the turbopack crates, eliminating all debug formatting machinery from release binaries entirely.Why?
ValueDebugFormatandValueDebugcontribute to release binary bloat. The field-level formatting logic (iterating struct fields, resolvingVcs, formatting collections recursively) and the per-typeValueDebugtrait registrations are purely debugging aids with no value in production binaries.Measured impact: -7.3 MiB (-5.5%) reduction in release
libnext_napi_bindings.sobinary size (from 126.26 MiB to 119.31 MiB).How?
ValueDebugtrait (debug/mod.rs):#[turbo_tasks::value_trait(no_debug)]withdbg()/dbg_depth()methods,ValueDebugFormatString, all blanket impls for collections/tuples/etc.impl<T: ?Sized> ValueDebug for T {}. This satisfies the supertrait bound on all value traits at zero cost — no per-type impl code is generated.ValueDebugFormattrait (debug/mod.rs):value_debug_formatmethod only exists under#[cfg(debug_assertions)]. In release builds, the trait is still present (for derive macros to reference) but has no methods.String,RcStr,Option,Vec,SmallVec,AutoSet,AutoMap,HashMap,FxIndexSet,FxIndexMap, tuples) are gated behinddebug_assertions.ValueDebugFormatString,PassthroughDebug,vdbg,internalsubmodule,value_debug_format_field) is compiled away.Proc-macros:
#[derive(ValueDebugFormat)]: emits a full impl withvalue_debug_formatmethod in debug builds, empty impl in release builds.#[derive(ValueDebug)]andvalue_implblocks: emit full debug impl in debug builds only — no release impl at all (the blanket marker trait impl covers it).#[turbo_tasks::value]: transparent types get#[cfg(debug_assertions)]on the manualValueDebugimpl. Non-transparent types use#[cfg_attr(debug_assertions, derive(turbo_tasks::debug::internal::ValueDebug))]so theinternalmodule is never referenced in release.#[turbo_tasks::value_trait]: theDynamic/Upcast/UpcastStrictimpls forBox<dyn ValueDebug>are gated behind#[cfg(debug_assertions)].Callers (
vc/mod.rs,vc/resolved.rs,read_ref.rs,mapped_read_ref.rs,macro_helpers.rs,alias_map.rs):impl ValueDebugFormatblocks and their imports are gated behind#[cfg(debug_assertions)].Verification
cargo check --release— clean (no errors, no warnings)cargo clippy --all-targets— clean