feat: native pure-Rust u64 FastPFOR codec#85
Open
CommanderStorm wants to merge 26 commits into
Open
Conversation
Adds a 64-bit (`u64`) FastPFOR codec to the pure-Rust side, which was previously 32-bit only. `FastPForWide128`/`FastPForWide256` compress `u64` values via the (now un-gated) `BlockCodec64` trait: FastPFOR-packed aligned blocks plus a variable-byte tail for the sub-block remainder. The wire format is byte-identical to the C++ `CppFastPFor128`/`CppFastPFor256` `encode64`/`decode64` paths, verified by parity unit tests and a 30-minute differential fuzz run (13.8M executions, no crashes). - bitpacking_wide: generic scalar packer for `u64` at widths 0..=64, whose bit-ordering is cross-checked against the proven u32 kernels. - fastpfor64: `FastPForWide<N>` with 65-entry exception tables, a 2-word exception bitmap, and u64 exception values. - Un-gate `BlockCodec64` so pure-Rust builds get 64-bit support. - Add the `fastpfor_u64` differential fuzz target and a README example. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
for more information, see https://pre-commit.ci
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Explain the Rust code on its own terms rather than by reference to the C++ implementation, drop a redundant test comment, and write comments as short single-sentence lines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consolidate the separate FastPForWide128/256 types into the existing FastPFor128/FastPFor256: each now implements AnyLenCodec (u32) and BlockCodec64 (u64), mirroring the C++ codecs that expose both widths from one type. The u64 engine is retained as a private field, so buffer reuse is preserved and the public API drops the extra FastPForWide* names. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
for more information, see https://pre-commit.ci
CommanderStorm
commented
Jul 17, 2026
The u32 and u64 codecs had near-identical encode_page/decode_page/best_bit implementations differing only in element width. Extract a single generic FastPForEngine<N, T> parameterized by a FastPForInt trait that abstracts the width-specific pieces (bit width, exception bitmap word count, pack/unpack, shifts). u32 keeps its hand-unrolled bit-packing kernels via trait dispatch, so there is no performance regression; u64 uses the generic wide packer. fastpfor.rs and fastpfor64.rs become thin wrappers over the engine. Net -296 lines with the page algorithm now written once. Verified byte-identical: u32 encode_compare fuzz (Rust==C++, 808K runs) and u64 differential fuzz (619K runs) both clean, plus the full test suite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
for more information, see https://pre-commit.ci
CommanderStorm
marked this pull request as ready for review
July 17, 2026 12:30
- Use Vec::clear() instead of truncate(0) in the encode_compare fuzz target (newer clippy flags truncate-to-zero). - Apply rustfmt to the generic-engine allow-attribute and the u64 fuzz target. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # src/test_utils.rs
for more information, see https://pre-commit.ci
Member
|
why not flatten pub struct FastPFor<const N: usize, T: FastPForInt = u32> {...} |
Member
|
i did a number of refactorings, and did a bit of a deep dive into benchmarks - making sure the new impl has the same speed (inlining always seems to be the key sadly). I think a bit more cleanup might be needed |
The pedantic `clippy::inline_always` lint was failing CI on the thin forwarders in the `FastPForInt` impls. The `#[inline(always)]` is intentional (documented above each fn); add an explicit `#[allow]` with reason so clippy stops flagging it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI's `just docs` denies rustdoc warnings. Fix the four broken links on the `FastPFor` doc comment: - `BlockCodec`, `FastPForBlock128`, `FastPForBlock256` now use explicit `crate::` paths (they're re-exported at the crate root, not in scope in this module). - `FastPForInt` is a private sealed trait, so drop the intra-doc link and leave it as plain code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CommanderStorm
commented
Jul 18, 2026
Comment on lines
+18
to
+21
| pub struct $name { | ||
| narrow: CompositeCodec<$block, VariableByte>, | ||
| wide: FastPFor<$n, u64>, | ||
| } |
Collaborator
Author
There was a problem hiding this comment.
not entirely happy with this.
So now that we have smushed u32 and u64 together, we have the worst of both worlds imo.
Your version means that
- the code uses a bit harder to read macros (likely fine)
- allocates both narrow AND wide
I would still prefer the engine abstraction because at least there, we are not allocating wide+narrow.
We can OnceCell it, but that also has costs for perf..
Collapse the two-field FastPFor codec into a single generic `FastPForCodec<N, T>` with one `inner: CompositeCodec<FastPFor<N,T>, VariableByte<T>>`. - Give `BlockCodec`/`AnyLenCodec` an associated `Elem` so the block engine and composite are one width-generic implementation instead of duplicated u32/u64 paths. - Unify `VariableByte` into a generic `VariableByte<T>` with u32 and u64 tail impls; drop the free `vbyte_encode64`/`vbyte_decode64` functions and `VariableByteWide`. - Split the public codec by width: `FastPFor128`/`FastPFor256` are u32; add `FastPForWide128`/`FastPForWide256` for u64. Each type serves one width, so it holds one codec. - Delete the redundant `BlockCodec64 for FastPFor<N,u64>`; the u64 type keeps a delegating `BlockCodec64` impl for C++ parity comparison. Wire format unchanged: C++ u64 parity tests pass. All tests, clippy, rustfmt, and rustdoc clean under both default and `cpp` features. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EqJPh46kx6YzhwUjX6EPDn
Replace the hand-written operator bounds, ZERO/ONE constants, and per-type significant_bits impls on FastPForInt with a PrimInt supertrait bound. Only the width-specific members (scratch buffers, packing/bitmap kernels) remain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EqJPh46kx6YzhwUjX6EPDn
CommanderStorm
commented
Jul 18, 2026
for more information, see https://pre-commit.ci
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.
Adds a native 64-bit (
u64) FastPFOR codec to the pure-Rust side