Use type-erased facet APIs for persistence callbacks#52
Merged
fasterthanlime merged 1 commit intomainfrom Jan 26, 2026
Merged
Conversation
Replace `facet_postcard::to_vec` with `peek_to_vec(Peek::new(...))` for serialization, and `facet_postcard::from_slice` with `from_slice_into` for deserialization in the persistence callbacks. The key insight is that while `Peek::new` and `heap_value.materialize()` are still generic, they are tiny (just pointer/shape manipulation). The heavy lifting happens in `peek_to_vec` and `from_slice_into` which are non-generic and compiled once. This reduces monomorphization in: - make_encode_record - make_decode_record - make_encode_incremental - make_apply_wal_entry Also updates facet to include the new `from_slice_into` API from facet-rs/facet#1932. Closes #51
There was a problem hiding this comment.
Pull request overview
This PR reduces monomorphization in picante's persistence layer by replacing generic serialization/deserialization APIs with type-erased alternatives. The key innovation is that while Peek::new and materialize() remain generic (but are tiny operations), the heavy lifting is done by non-generic functions peek_to_vec and from_slice_into that are compiled only once.
Changes:
- Replace
facet_postcard::to_vecwithpeek_to_vec(Peek::new(...))for serialization - Replace
facet_postcard::from_slicewith a multi-step type-erased deserialization flow usingfrom_slice_into - Update facet dependency from 0.42.0 to 0.43.2 to access new type-erased APIs
Reviewed changes
Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| crates/picante/src/ingredient/derived.rs | Updated four persistence callback functions (make_encode_record, make_decode_record, make_encode_incremental, make_apply_wal_entry) to use type-erased serialization/deserialization APIs, reducing monomorphization while maintaining functionality |
| Cargo.lock | Updated facet dependencies from 0.42.0 to 0.43.2, added new transitive dependencies (cobs, corosensei, embedded-io, foldhash, iddqd, object, postcard, thiserror), and updated cranelift and wasmtime dependencies to newer versions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Open
fasterthanlime
added a commit
that referenced
this pull request
Jan 26, 2026
… functions PR #52 added type-erased APIs but kept them inside the generic closures, causing the entire closure body to be monomorphized for each K,V combination. This extracts the heavy lifting into two non-generic helper functions: - encode_with_peek: wraps peek_to_vec, compiled once - decode_to_heap_value: wraps alloc + from_slice_into + build, compiled once The closures now only contain the tiny generic parts (Peek::new, materialize). Measured impact on dodeca: - Before this PR (PR #52): 2,349k LLVM IR lines - After this PR: 2,294k LLVM IR lines - Savings: 55k lines (also 21k better than pre-#52 baseline)
1 task
fasterthanlime
added a commit
that referenced
this pull request
Jan 26, 2026
… functions (#53) PR #52 added type-erased APIs but kept them inside the generic closures, causing the entire closure body to be monomorphized for each K,V combination. This extracts the heavy lifting into two non-generic helper functions: - encode_with_peek: wraps peek_to_vec, compiled once - decode_to_heap_value: wraps alloc + from_slice_into + build, compiled once The closures now only contain the tiny generic parts (Peek::new, materialize). Measured impact on dodeca: - Before this PR (PR #52): 2,349k LLVM IR lines - After this PR: 2,294k LLVM IR lines - Savings: 55k lines (also 21k better than pre-#52 baseline)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
facet_postcard::to_vecwithpeek_to_vec(Peek::new(...))for serializationfacet_postcard::from_slicewithfrom_slice_intofor deserializationfrom_slice_intoAPI from Reduce monomorphization and add from_slice_into APIs for msgpack/postcard facet-rs/facet#1932How it works
The key insight is that while
Peek::newandheap_value.materialize()are still generic, they are tiny (just pointer/shape manipulation). The heavy lifting happens in:peek_to_vec(peek)- non-generic, compiled oncefrom_slice_into(bytes, partial)- non-generic, compiled onceThis reduces monomorphization in the persistence callbacks:
make_encode_recordmake_decode_recordmake_encode_incrementalmake_apply_wal_entryTest plan
Closes #51