next.js
2af85b58 - make rcstrs on the heap/static slightly smaller (#93805)

Commit
90 days ago
make rcstrs on the heap/static slightly smaller (#93805) ### What? Splits the previously unified `PrehashedString` (which held a `Payload` enum of `String | &'static str`) into two separate types: `StaticPrehashedString { value: &'static str, hash: u64 }` for atoms produced by `rcstr!` / `make_const_prehashed_string`, and `DynamicPrehashedString { value: Box<str>, hash: u64 }` for atoms held in an `Arc`. The static and dynamic paths were already distinguished by the `STATIC_TAG` / `DYNAMIC_TAG` bits in `RcStr`, so the runtime branch on enum discriminant was redundant. ### Why? - **16 bytes saved per heap-allocated `RcStr` value .** Dynamic atoms drop the `String::capacity` field (which was always equal to `len` since the contents are immutable) and because they are stored in a `triomphe::Arc` this drops the Arc payload to 32 bytes instead of 40 which matches a mimalloc bucket (previously we were rounded up to a 48 byte bucket) so we save 16 bytes. - **8 bytes saved per static `RcStr` value.** The linker will optimally align our 24 byte struct. - Removes a layer of dispatch on the hot path (`as_str`, `==`, `Hash`) — typed deref to the correct variant instead of matching on `Payload`. (i.o.w. one 'descreminent' traversal instead of 2) ### How? - `dynamic.rs`: `Payload` enum removed; two structs replace `PrehashedString`. `deref_from` split into `deref_static` and `deref_dynamic`. `restore_arc` returns `Arc<DynamicPrehashedString>`. - `lib.rs`: `as_str` and `into_owned` dispatch on `tag()` (STATIC vs DYNAMIC vs INLINE) rather than `location()`. New `heap_hash_and_str` helper for `PartialEq` and `Hash` to share the static/dynamic branch. `into_owned`'s `try_unwrap` arm uses `String::from(Box<str>)` which reuses the box allocation (still O(1)). - `turbo-rcstr-macros`: emit `::turbo_rcstr::StaticPrehashedString` instead of `::turbo_rcstr::PrehashedString`. - Added a comment on `DynamicPrehashedString` noting the future move to `triomphe::ThinArc` to fold the two heap allocations (Arc header + boxed bytes) into one. Deferred because that change would make `RcStr::from(String)` copy the bytes, invalidating the documented cheap `String -> RcStr -> String` round-trip — wants a separate evaluation. <!-- NEXT_JS_LLM_PR -->
Author
Parents
Loading