Skip to content

[Prototype] Feature-gate heavy derives (MallocSizeOf, ToShmem, SpecifiedValueInfo, ToTyped) to improve compile times - #3

Draft
nicoburns wants to merge 1 commit into
mainfrom
devin/1785851813-feature-gate-heavy-derives
Draft

[Prototype] Feature-gate heavy derives (MallocSizeOf, ToShmem, SpecifiedValueInfo, ToTyped) to improve compile times#3
nicoburns wants to merge 1 commit into
mainfrom
devin/1785851813-feature-gate-heavy-derives

Conversation

@nicoburns

Copy link
Copy Markdown
Member

Summary

Prototype / experiment — makes the heavy trait derives in the stylo crate optional via cargo features, to reduce compile times for embedders that don't need them. Defaults are unchanged: all features stay on by default (and are forced on by gecko), so existing consumers compile the exact same code.

New features on the stylo crate:

Feature Gates Needed for
malloc_size_of derive(MallocSizeOf) expansions (~860 sites) + memory-reporting fns memory reporting
to_shmem derive(ToShmem) expansions + selectors/to_shmem + ToShmem impls Gecko shared-memory UA sheets
specified_value_info derive(SpecifiedValueInfo) + the per-property SUPPORTED_TYPES/completion-keyword tables (supports_type, collect_property_completion_keywords) devtools value autocomplete
typed_om derive(ToTyped), the typed_om module, and all reification code Typed OM

default = ["servo", "malloc_size_of", "to_shmem", "specified_value_info", "typed_om"]. To disable the gates: default-features = false, features = ["servo"].

Mechanism

Rather than sprinkling #[cfg_attr(feature = ..., derive(...))] over ~940 derive sites (huge diff, and awkward to keep in sync with upstream), this exploits the existing central mod derives re-export hub in style/lib.rs: when a feature is off, the derive name is re-pointed at a no-op derive macro (added to style_derive) that accepts the same helper attributes (#[shmem(...)], #[value_info(...)], #[typed(...)], #[ignore_malloc_size_of]) but expands to nothing:

#[cfg(feature = "malloc_size_of")]
pub(crate) use malloc_size_of_derive::MallocSizeOf;
#[cfg(not(feature = "malloc_size_of"))]
pub(crate) use style_derive::NoopMallocSizeOf as MallocSizeOf;

This skips both the derive expansion and the type-checking of the expanded impls, which is where the compile time goes. The rest of the diff is #[cfg(feature = ...)] on the handwritten trait impls, imports, and call sites that require the derived impls to exist (typed_om reification code, PropertyDeclarationBlock: ToShmem, the property value-info tables in properties.mako.rs, memory-reporting entry points, etc.). The traits themselves remain defined unconditionally, so generic bounds still compile.

Notes:

  • selectors/to_shmem moved from the servo feature into the new to_shmem feature.
  • CalcNodeLeaf's ToTyped supertrait is replaced by a CalcLeafToTyped alias that is literally ToTyped when typed_om is on, and a blanket-implemented empty trait when off.
  • With gates off, some imports/helpers become unused; a crate-level cfg_attr(..., allow(unused_imports, dead_code)) (active only when any gate is off) keeps that config warning-free without churning hundreds of import lines. Default builds keep full warnings.
  • All four derives were tractable to gate, including MallocSizeOf — the no-op-derive approach avoided the per-site yak-shave.

Compile-time measurements

2-core Linux VM, rustc 1.95.0, debug profile. "Gated off" = -p stylo --no-default-features --features servo.

Measurement Default (all on) Gated off Δ
Cold cargo build (workspace) 98.2 s 91.0 s −7%
stylo crate unit (cargo --timings) 55.6 s 48.7 s −12%
Cold cargo check (workspace) 42.7 s 39.2 s −8%
touch style/lib.rs && cargo check 9.0 s 7.7 s −15%

Default-feature times are identical to pre-change baseline (98 s / 42 s / 9 s), confirming default behavior is unchanged. The win is real but more modest than the derive counts might suggest — the remaining frontend time is dominated by the always-on derives (ToCss, ToComputedValue, ToResolvedValue, Parse, Animate, ...) and general type-checking of the ~276k-line crate.

Validation

  • cargo check (default features): clean
  • cargo check -p stylo --no-default-features --features servo: clean (no warnings)
  • cargo fmt --check: clean

The gecko configuration compiles the same code as before (it force-enables all four features) but wasn't buildable here (needs bindgen/mozbuild). Intermediate feature combinations (e.g. typed_om off but specified_value_info on) haven't been exhaustively tested.

Link to Devin session: https://app.devin.ai/sessions/e8fbaf225d8a40cea95584e606d17c72
Requested by: @nicoburns

@nicoburns nicoburns self-assigned this Aug 4, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

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.

1 participant