Skip to content

Add structured decoding#79

Merged
frankmcsherry merged 2 commits intomasterfrom
decoded_store
Mar 14, 2026
Merged

Add structured decoding#79
frankmcsherry merged 2 commits intomasterfrom
decoded_store

Conversation

@frankmcsherry
Copy link
Copy Markdown
Owner

@frankmcsherry frankmcsherry commented Mar 14, 2026

Written with Claude, this adds a structured form of decoding that does not use iteration, as this proves to be hard to fully elide when not used. The type DecodedStore essentially provides random access to slices, and could be generalized in the future with a trait that does something like this (not std::ops::Index, because the lifetimes would be too short).

Claude says:

  Summary

  Introduces DecodedStore, a zero-allocation view into indexed-encoded &[u64]
   data that provides O(1) random access to individual slices. The new
  FromBytes::from_store method uses it to give each field independent access
  at its compile-time-known offset, replacing the iterator-based from_u64s
  path.

  The key difference from the iterator approach: each field's access is
  independent — no sequential dependency, no iterator state to advance. This
  lets LLVM fully eliminate unused fields when only one field of a tuple is
  accessed.

  Assembly: critical-path instructions to access one field

  Accessing field 0 of a k-tuple of u64 columns, from raw &[u64] to returned
  value:

  ┌─────────────┬────────────────────────┬──────────────────────┐
  │ Tuple width │  from_bytes (before)   │  from_store (after)  │
  ├─────────────┼────────────────────────┼──────────────────────┤
  │ k=3         │ 133 insns, 14 branches │ 49 insns, 3 branches │
  ├─────────────┼────────────────────────┼──────────────────────┤
  │ k=8         │ 273 insns, 29 branches │ 49 insns, 3 branches │
  ├─────────────┼────────────────────────┼──────────────────────┤
  │ k=16        │ 545 insns, 56 branches │ 49 insns, 3 branches │
  └─────────────┴────────────────────────┴──────────────────────┘

  Constant in k, constant in field position (49 for field 0, 54 for any other
   field). LLVM eliminates unused fields across all type combinators —
  tuples, Results, Options, Vecs, Strings, and arbitrary nesting.

  ┌────────────────────────┬───────────────────┬────────────┬────────────┐
  │          Type          │     Accessing     │ from_bytes │ from_store │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤   
  │ (u64, u64, u64)        │ f0                │ 133 / 14   │ 49 / 3     │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤   
  │ (u64 x8)               │ f0                │ 273 / 29   │ 49 / 3     │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤
  │ (u64 x16)              │ f0                │ 545 / 56   │ 49 / 3     │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤
  │ (u64, Result<u64,u64>) │ f0, skip Result   │ 132 / 11   │ 49 / 3     │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤
  │ (u64, String, Vec)     │ f0, skip          │ 133 / 14   │ 49 / 3     │
  │                        │ String+Vec        │            │            │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤
  │ (u64, (u64, (u64,      │ innermost field   │ 133 / 14   │ 54 / 4     │
  │ u64)))                 │                   │            │            │
  ├────────────────────────┼───────────────────┼────────────┼────────────┤
  │ ((u64 x4), (u64 x4))   │ .1.3              │ 273 / 29   │ 54 / 4     │
  └────────────────────────┴───────────────────┴────────────┴────────────┘

  (Format: critical-path instructions / branches. The from_bytes column does
  not have a k=16 Result measurement but would be proportionally larger.)


  Changes

  - DecodedStore: two-field struct (index and words), constructed in O(1),
  provides .get(k) -> (&[u64], u8) with non-panicking random access
  - FromBytes::from_store: new method with overrides for all types in the
  library, used by Stash::borrow
  - Removes from_u64s, decode_u64s, and from_byte_slices (all superseded)
  - Adds from_store to the derive macro for structs and enums

frankmcsherry and others added 2 commits March 14, 2026 16:59
…rage

DecodedStore is a zero-allocation view into Indexed-encoded data that
provides O(1) random access to individual slices. from_store on
FromBytes uses it to give each field independent access at its
compile-time-known offset, eliminating the iterator dependency chain.

Assembly: accessing any field of any tuple width is now 49-54
instructions on the critical path, constant in both k (tuple width)
and field position. LLVM fully eliminates unused fields across all
type combinators: tuples, Results, Options, Vecs, Strings, and
arbitrary nesting.

Also adds from_u64s and from_store overrides to all remaining
FromBytes impls (Usizes, Isizes, Chars, U128s, I128s, Fixeds,
Strides, Empties, Bools, Durations) to ensure no leaf type breaks
the optimization chain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These are superseded by from_store + DecodedStore which provides
random access without iterator overhead. The FromBytes trait now has
three methods beyond from_bytes: from_store, element_sizes, and
validate. The derive macro generates from_store automatically.

Also fixes references to the removed Indexed struct in doc comments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@frankmcsherry frankmcsherry merged commit e4bc02a into master Mar 14, 2026
6 checks passed
@frankmcsherry frankmcsherry deleted the decoded_store branch March 14, 2026 21:40
@github-actions github-actions bot mentioned this pull request Mar 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant