Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
eb6ba62
wasm32-pins: land the 32-bit execution leg with today's boundaries pi…
plaidfinch Aug 18, 2026
78c6537
before: walk the byte decode doors over raw bytes, off the borrowed view
plaidfinch Aug 18, 2026
1c47d7c
before: compute Bits::len at u64 width, checked back to usize
plaidfinch Aug 18, 2026
65eaf9f
before: assemble the rank decoder's numerator from bytes, never a shift
plaidfinch Aug 18, 2026
9d38eef
wasm32-pins: state pin invariants in the present tense
plaidfinch Aug 18, 2026
7ea3df5
before: classify the remaining 32-bit widening sites inline
plaidfinch Aug 18, 2026
456dc0f
docs: keep the new byte-door and pin doc summaries under the doclint cap
plaidfinch Aug 18, 2026
cfa7c7e
before: restore the encode shift's metered spelling; tighten the byte…
plaidfinch Aug 18, 2026
f34f4b3
before: re-pin rank_decode's worst heap families after the byte assembly
plaidfinch Aug 18, 2026
39b237e
wasm32-pins: red-first pins for five newly scoped 32-bit boundaries
plaidfinch Aug 18, 2026
16cb4df
wasm32-pins: keep the new pins' doc summaries under the doclint cap
plaidfinch Aug 18, 2026
5d167a6
before: replace the borrowed bit view with the crate-owned BitsView
plaidfinch Aug 18, 2026
f6c0a6a
before: tighten the skyline-decode heap envelopes to the once-allocat…
plaidfinch Aug 18, 2026
b802e1b
before: disambiguate the skyline encode doc link
plaidfinch Aug 19, 2026
83e61b4
before: replace the bitvec build buffer with the crate-owned BitsBuf
plaidfinch Aug 19, 2026
05d87e1
before: denominate bit streams in u64 end to end; gate encoded_bits m…
plaidfinch Aug 19, 2026
c75d502
wasm32-pins: pin the memory bound as the only terminal past every coo…
plaidfinch Aug 19, 2026
8da5792
suanpan: stream limbs past the backend and read totals back out as limbs
plaidfinch Aug 19, 2026
79a944a
before: total rank arithmetic to the working-set ceiling on 32-bit ta…
plaidfinch Aug 19, 2026
35a09c5
before: sweep the last build-substrate ghosts and a dead assert leg
plaidfinch Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .cargo/mutants.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ additional_cargo_args = ["--all-features"]
exclude_re = [
# --- suanpan::accumulator ---

# Proven equivalent: read_magnitude's final carry has magnitude at
# Proven equivalent: read_digits' final carry has magnitude at
# most 3 (bound derived in the comment at the site), so each high-part
# drain emits its whole value in its first digit and the mutated shift
# direction has an empty discriminating class.
"accumulator\\.rs.*: replace >>= with <<= in Accumulator::read_magnitude",
"accumulator\\.rs.*: replace >>= with <<= in Accumulator::read_digits",

# Performance genre, owner-declared benign fast path: the identity
# guard routes cost and representation only (the comment at the site
Expand Down Expand Up @@ -139,7 +139,7 @@ exclude_re = [
# Proven equivalent, line-pinned (the match arm's guard shares the
# operator pattern and is killed): at equal magnitude the cross and
# shrink paths both land on the positive zero zigzag.
"grow\\.rs:457:38: replace < with <= in recode",
"grow\\.rs:463:38: replace < with <= in recode",

# --- before::version::skyline::fill / prescan ---

Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ rand = "0.8"

[dev-dependencies]
rumors = { path = ".", features = ["test-internals", "conformance"] }
before = { path = "crates/before", features = ["borsh"] }
# The meter feature lights before's instrument surface for this crate's
# own tests: the conservation suite reads the exact-bit-length observation
# (`encoded_bits`) it denominates identity conservation in.
before = { path = "crates/before", features = ["borsh", "meter"] }
proptest = "1"
criterion = { version = "0.5", features = ["html_reports"] }
insta = "1.47"
Expand Down
40 changes: 0 additions & 40 deletions crates/before-fuelscape/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions crates/before-fuelscape/src/count/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const CENSUS_BITS: usize = 8 * CENSUS_BYTES - 1;
/// and tallies acceptances per live bit length. The sweep fans out over
/// rayon; per-chunk histograms add commutatively, so the fan-out cannot
/// change any count.
fn decoder_census(accept: impl Fn(&[u8]) -> Option<usize> + Sync) -> Vec<u64> {
fn decoder_census(accept: impl Fn(&[u8]) -> Option<u64> + Sync) -> Vec<u64> {
let empty = || vec![0u64; CENSUS_BITS + 1];
let mut census = empty();
for len in 1..=CENSUS_BYTES {
Expand All @@ -147,10 +147,12 @@ fn decoder_census(accept: impl Fn(&[u8]) -> Option<usize> + Sync) -> Vec<u64> {
}
if let Some(bits) = accept(&buf[..len]) {
assert!(
bits < 8 * len,
bits < 8 * len as u64,
"decoder reported {bits} live bits from a {len}-byte input"
);
hist[bits] += 1;
// In range per the assert above: census inputs are a few
// bytes, so the bit length indexes the histogram.
hist[bits as usize] += 1;
}
hist
})
Expand Down
4 changes: 2 additions & 2 deletions crates/before-fuelscape/src/sample/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ proptest! {
.expect("every byte size down to 1 has canonical versions");
prop_assert_eq!(draw.bytes.len(), size);
let version = Version::decode(&draw.bytes[..]).expect("sampler output must be canonical");
prop_assert_eq!(version.encoded_bits(), draw.bits);
prop_assert_eq!(version.encoded_bits(), draw.bits as u64);
prop_assert_eq!(version.encode(), draw.bytes);
}

Expand All @@ -257,7 +257,7 @@ proptest! {
.expect("every byte size down to 1 has canonical parties");
prop_assert_eq!(draw.bytes.len(), size);
let party = Party::decode(&draw.bytes[..]).expect("sampler output must be canonical");
prop_assert_eq!(party.encoded_bits(), draw.bits);
prop_assert_eq!(party.encoded_bits(), draw.bits as u64);
prop_assert_eq!(party.encode(), draw.bytes);
}
}
13 changes: 9 additions & 4 deletions crates/before/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ rustdoc-args = ["--html-in-header", "docs/fuelscape-header.html"]
serde_json = "1"

[dependencies]
bitvec = "1"
bytes = "1"
dashu-int = { version = "0.5", default-features = false, features = ["std"] }
suanpan = { path = "../suanpan" }
Expand All @@ -32,6 +31,9 @@ serde = { version = "1", optional = true, default-features = false, features = [
borsh = { version = "1", optional = true }

[dev-dependencies]
# The emit_probe example's external comparison baseline: the production
# build buffer is the crate-owned BitsBuf, and nothing shipped links bitvec.
bitvec = "1"
proptest = "1"
serde_json = "1"
criterion = "0.5"
Expand Down Expand Up @@ -60,12 +62,15 @@ oracle = []
# worst-case inputs and read the counters they envelope, and the public
# operation surface roster (`src/surface.rs`) as `before::surface`, so external
# instrument crates can bind their coverage to the rows the surface-coverage
# suite enforces totality over. Bench/test-only.
# suite enforces totality over, and the instrument-side value observations
# (`encoded_bits` on `Party`/`Version`/`Clock`), the exact bit-length
# denomination the meters and boundary pins read. Bench/test-only.
meter = []
# Exposes the named algebraic-law predicates (`src/laws.rs`) as `before::laws`,
# so the fuzz workspace can drive the same law collection the in-tree proptests
# assert. Test/fuzz-only.
laws = []
# assert. Implies `meter`: the representational laws read the instrument-side
# observations (`encoded_bits`) that feature exposes. Test/fuzz-only.
laws = ["meter"]
# Counts big-integer limb-scale work (operand limbs per `Base` operation:
# arithmetic, comparison, equality, and hashing; plus one value-width record per
# decoded wide-gamma value) into a process-global counter read via
Expand Down
2 changes: 1 addition & 1 deletion crates/before/benches/party.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! `Party` benchmarks: the optimized packed-`BitVec` implementation against the naive
//! `Party` benchmarks: the optimized packed-bit-stream implementation against the naive
//! recursive oracle, on the same randomized trees (see `common`). Codec ops have no
//! oracle counterpart and are timed for the impl alone.

Expand Down
4 changes: 2 additions & 2 deletions crates/before/benches/presize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn outgrow_family() -> Vec<(u32, Version, Party)> {
fn resident_line<T>(
site: &str,
x: impl std::fmt::Display,
out_bits: usize,
out_bits: u64,
build: impl FnOnce() -> T,
) {
let arm = common::alloc_arms();
Expand Down Expand Up @@ -196,7 +196,7 @@ fn resident_report() {
let plan = common::plan(&mut r, n, 1);
let v = common::impl_versions(&plan, 1).pop().expect("one group");
let s = v.to_string();
resident_line("display", n, s.len() * 8, || v.to_string());
resident_line("display", n, s.len() as u64 * 8, || v.to_string());
resident_line("parse", n, v.encoded_bits(), || {
s.parse::<Version>().expect("a rendered version parses")
});
Expand Down
11 changes: 6 additions & 5 deletions crates/before/examples/code_study.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,17 @@ impl Code {
// ─── the skyline stream walker ──────────────────────────────────────────────

/// Read bit `i` of an Msb0 packed stream.
fn bit(bytes: &[u8], i: usize) -> bool {
(bytes[i / 8] >> (7 - i % 8)) & 1 == 1
fn bit(bytes: &[u8], i: u64) -> bool {
// An in-range byte index fits `usize`: it indexes an allocated buffer.
(bytes[(i / 8) as usize] >> (7 - i % 8)) & 1 == 1
}

/// Walk one stored version stream, recording payload values per class and
/// asserting the exact reconciliation identity.
fn walk(v: &Version, corpus: &mut Corpus) {
let bytes = v.as_bytes();
let bits = v.encoded_bits();
let mut pos = 0usize;
let mut pos = 0u64;
let mut pending = 1u64; // subtrees still owed
let mut nodes = 0u128;
let mut first = true;
Expand All @@ -272,7 +273,7 @@ fn walk(v: &Version, corpus: &mut Corpus) {
}
pending -= 1;
// Leaf (`1`) payload: one gamma code. Count the unary prefix.
let mut k = 0usize;
let mut k = 0u64;
while !bit(bytes, pos) {
pos += 1;
k += 1;
Expand Down Expand Up @@ -301,7 +302,7 @@ fn walk(v: &Version, corpus: &mut Corpus) {
}
} else {
pos += k; // skip the wide mantissa remainder
let l = (k + 1) as u64;
let l = k + 1;
hist.record_wide(l);
for (slot, (_, code)) in code_bits.iter_mut().zip(CODES) {
*slot = match (*slot, code.len_wide(l)) {
Expand Down
37 changes: 20 additions & 17 deletions crates/before/examples/emit_probe.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
//! Primitive-cost probe for the emission machinery.
//!
//! Measures the raw output-side primitives the join/tick sweeps spend
//! their cycles in (per-bit `bitvec` pushes, per-leaf heap-allocated
//! code buffers, bit-addressed splices) against word-buffered
//! equivalents, on the same workload shape (~5k leaves, 3-9 bit codes,
//! 75k output bits).
//! Measures candidate output-side primitive shapes (per-bit pushes into a
//! general bit vector — the external `bitvec` baseline — per-leaf
//! heap-allocated code buffers, bit-addressed splices) against the
//! word-buffered equivalents the crate's own builder ships, on the
//! join/tick sweeps' workload shape (~5k leaves, 3-9 bit codes, 75k
//! output bits).
//!
//! Usage: cargo run -p before --profile bench --example emit_probe

use bitvec::prelude::*;
use std::hint::black_box;
use std::time::Instant;

type BitsMut = BitVec<u8, Msb0>;
type BaselineBits = BitVec<u8, Msb0>;

const LEAVES: usize = 5000;

Expand Down Expand Up @@ -46,8 +47,9 @@ fn bench(name: &str, iters: u32, mut f: impl FnMut() -> usize) {
);
}

/// A minimal word-buffered MSB-first bit writer: the shape a
/// `PackedBuilder` replacement would have.
/// A minimal word-buffered MSB-first bit writer: the staging discipline
/// the crate's own `PackedBuilder` ships, reproduced standalone so the
/// comparison needs no crate internals.
struct WordWriter {
words: Vec<u64>,
/// Bits already committed to `words` (multiple of 64).
Expand Down Expand Up @@ -94,10 +96,10 @@ fn main() {
let total_bits: usize = codes.iter().map(|(_, l)| 2 + *l as usize).sum();
println!("leaves={LEAVES} total output bits≈{total_bits}");

// 1. Per-bit bitvec push: the current PackedBuilder discipline
// 1. Per-bit bitvec push: the external baseline at its simplest
// (1 flag push + per-bit code pushes per leaf).
bench("bitvec push per bit", 2000, || {
let mut out: BitsMut = BitVec::with_capacity(total_bits);
let mut out: BaselineBits = BitVec::with_capacity(total_bits);
for &(code, len) in &codes {
out.push(true);
for i in (0..len).rev() {
Expand All @@ -108,12 +110,13 @@ fn main() {
out.len()
});

// 2. Current per-leaf heap code + extend_from_bitslice splice: what
// gamma_code + SkylineBuilder::leaf actually do.
// 2. Per-leaf heap code + extend_from_bitslice splice: the external
// baseline shaped like a builder that allocates each code before
// splicing it.
bench("bitvec alloc code + splice per leaf", 2000, || {
let mut out: BitsMut = BitVec::with_capacity(total_bits);
let mut out: BaselineBits = BitVec::with_capacity(total_bits);
for &(code, len) in &codes {
let mut c: BitsMut = BitsMut::new();
let mut c: BaselineBits = BaselineBits::new();
for i in (0..len).rev() {
c.push((code >> i) & 1 == 1);
}
Expand All @@ -137,8 +140,8 @@ fn main() {

// 4. Bulk copy comparison: one 37.5k-bit misaligned splice, bitvec vs
// word shifts (the tick grow-path verbatim copy).
let src: BitsMut = {
let mut v = BitsMut::new();
let src: BaselineBits = {
let mut v = BaselineBits::new();
let mut state = 7u64;
for _ in 0..37_500 {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
Expand All @@ -150,7 +153,7 @@ fn main() {
"bitvec extend_from_bitslice 37.5kbit misaligned",
2000,
|| {
let mut out: BitsMut = BitVec::with_capacity(38_000);
let mut out: BaselineBits = BitVec::with_capacity(38_000);
out.push(true); // force misalignment
out.extend_from_bitslice(&src[3..]);
out.len()
Expand Down
2 changes: 1 addition & 1 deletion crates/before/examples/space_consumption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ fn build_population(n: usize) -> Vec<Clock> {
/// `⌈bits/8⌉` per stamp (the per-stamp ceiling is what biases the byte mean).
fn mean_stamp_sizes(clocks: &[Clock]) -> (f64, f64) {
let n = clocks.len() as f64;
let bits: usize = clocks.iter().map(Clock::encoded_bits).sum();
let bits: u64 = clocks.iter().map(Clock::encoded_bits).sum();
let bytes: usize = clocks.iter().map(|c| c.encode().len()).sum();
(bits as f64 / n, bytes as f64 / n)
}
Expand Down
Loading