Repository navigation
Store dictionaries as sorted vectors with inline name keys - #610
Merged
Merged
Conversation
Dictionary entries move from a BTreeMap<Vec<u8>, ObjectVariant> to a private Vec<(PdfName, ObjectVariant)> sorted by key, looked up by binary search. PdfName stores names of up to 22 bytes inline, so dictionary keys no longer allocate, and the parser builds names straight from the input unless they contain # escapes. Dictionary::new and its sort-and-dedup pass are removed. The parser inserts each entry as it reads it, so a repeated key keeps its last value as before; decryption decrypts values in place through iter_mut; inline-image normalization builds its dictionary directly. Callers with loose entries use the new FromIterator impl. optional_entries and lenient_entries borrow the resolved sub-dictionary instead of cloning it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
Dictionarystores its entries in a privateVec<(PdfName, ObjectVariant)>sorted by key, instead of a publicBTreeMap<Vec<u8>, ObjectVariant>. Lookups use binary search, and iteration stays in key order.PdfNamestores names of up to 22 bytes inline, so dictionary keys no longer allocate. Longer names use a sharedArc<[u8]>.parse_namereturns aPdfNameand only allocates when the name contains#escapes.Dictionary::newand its sort-and-dedup pass are removed:inserts each entry as it reads it, so a repeated key keeps its last value, as with the oldBTreeMap;iter_mut();FromIteratorimpl.optional_entriesandlenient_entriesborrow the resolved sub-dictionary instead of cloning it.PdfString { bytes: Arc<[u8]> }, so the 73read::<Arc<[u8]>>sites still only clone anArcand allocate nothing.Benchmarks
document_openon the shipped profile (opt-level "z", fat LTO). Medians of 5 interleaved rounds againstmain, run before the parser switched to inserting keys as it reads them:Inserting each key in sorted position as the parser reads it, instead of sorting once at the end, measured 0.2–2% slower on six documents and slightly faster on two, close to the noise floor. The final code was not benchmarked against
maindirectly.Inline keys compared with
Arc<[u8]>keys, everything else identical: −1.8% to −3.1% on four documents, within noise on the rest.Test plan
cargo test --workspace --exclude pdf-graphics-skia --exclude pdf-conformancecargo clippy --workspace --all-targets --exclude pdf-graphics-skia --exclude pdf-conformance -- -D warningscargo fmt --all --check, minimal-feature check🤖 Generated with Claude Code