format: monomorphise the Storage parsers so local files stay as fast

Every `*_in` core and the read helpers take `file: &S` with
`S: Storage + ?Sized` instead of `&dyn Storage`, and the `&[u8]`
wrappers pass the slice itself, so they compile to a `[u8]` instance:
`as_contiguous()` inlines to `Some(self)` and each structure read is the
slice code's bounds check again, with no indirect call. `&dyn Storage`
still works (`S = dyn Storage`); there is one parser implementation.

Also, so the structure reads cost no more than the slice checks did:
- ObjectHeader::parse_in reads the prefix once (signature included)
  instead of the signature and then the prefix: two reads for a
  one-chunk header instead of three on a range backend;
- the symbol-table node and group B-tree (v1) loops walk their entries
  with chunks_exact over the bytes read, and the node's redundant second
  bounds check is gone (the entries' read is the check, same error);
- a version-1 header's message list is sized from its (capped) count.
Same results and errors; the unit and equivalence tests are unchanged.

New Criterion bench `clawhdf5/benches/local_metadata_bench.rs` over a
400-group version-1 file written by h5py (new fixture
`v1_groups_400.h5`): ObjectHeader::parse, symbol-table nodes, the group
B-tree walk and a facade listing, using only APIs that exist at f2ff2c4
so it builds there for an A/B.

Provisional A/B against f2ff2c4 (busy machine, not for docs): both
builds linked into one binary and timed in alternation, 200 rounds;
median ratio new/old: facade listing -0.5% to -3.5% (was +14%),
ObjectHeader::parse +1% to +2% (was +25%), symbol-table nodes -18%,
group B-tree walk -18%, local-heap names and resolve_group_children
within +-1.5%. An old-vs-old-copy run shows +-2% from code layout alone.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 14:22:37 -05:00
co-authored by Claude Opus 5.5
parent d2b25f154f
commit 052098bf36
18 changed files with 315 additions and 219 deletions
+24 -24
View File
@@ -254,13 +254,13 @@ pub fn parse_sohm_table(
nindexes: u8,
offset_size: u8,
) -> Result<SohmTable, FormatError> {
parse_sohm_table_in(&file_data, table_addr as u64, nindexes, offset_size)
parse_sohm_table_in(file_data, table_addr as u64, nindexes, offset_size)
}
/// [`parse_sohm_table`] over any [`Storage`]: one read of the signature,
/// one of every index entry.
pub fn parse_sohm_table_in(
file: &dyn Storage,
pub fn parse_sohm_table_in<S: Storage + ?Sized>(
file: &S,
table_addr: u64,
nindexes: u8,
offset_size: u8,
@@ -384,13 +384,13 @@ pub fn parse_sohm_list(
num_messages: u16,
offset_size: u8,
) -> Result<Vec<SohmEntry>, FormatError> {
parse_sohm_list_in(&file_data, list_addr as u64, num_messages, offset_size)
parse_sohm_list_in(file_data, list_addr as u64, num_messages, offset_size)
}
/// [`parse_sohm_list`] over any [`Storage`]: one read of the signature, one
/// of every entry.
pub fn parse_sohm_list_in(
file: &dyn Storage,
pub fn parse_sohm_list_in<S: Storage + ?Sized>(
file: &S,
list_addr: u64,
num_messages: u16,
offset_size: u8,
@@ -420,14 +420,14 @@ pub fn parse_sohm_btree_entries(
offset_size: u8,
length_size: u8,
) -> Result<Vec<SohmEntry>, FormatError> {
parse_sohm_btree_entries_in(&file_data, btree_addr as u64, offset_size, length_size)
parse_sohm_btree_entries_in(file_data, btree_addr as u64, offset_size, length_size)
}
/// [`parse_sohm_btree_entries`] over any [`Storage`]. The v2 B-tree is not
/// read over [`Storage`] yet, so this needs the whole file in memory
/// ([`FormatError::ContiguousStorageRequired`] otherwise).
pub fn parse_sohm_btree_entries_in(
file: &dyn Storage,
pub fn parse_sohm_btree_entries_in<S: Storage + ?Sized>(
file: &S,
btree_addr: u64,
offset_size: u8,
length_size: u8,
@@ -455,12 +455,12 @@ pub fn load_sohm_table(
offset_size: u8,
length_size: u8,
) -> Result<Option<SohmTable>, FormatError> {
load_sohm_table_in(&file_data, offset_size, length_size)
load_sohm_table_in(file_data, offset_size, length_size)
}
/// [`load_sohm_table`] over any [`Storage`].
pub fn load_sohm_table_in(
file_data: &dyn Storage,
pub fn load_sohm_table_in<S: Storage + ?Sized>(
file_data: &S,
offset_size: u8,
length_size: u8,
) -> Result<Option<SohmTable>, FormatError> {
@@ -498,12 +498,12 @@ pub fn message_data_with_sohm<'a>(
offset_size: u8,
length_size: u8,
) -> Result<Cow<'a, [u8]>, FormatError> {
message_data_with_sohm_in(&file_data, msg, offset_size, length_size)
message_data_with_sohm_in(file_data, msg, offset_size, length_size)
}
/// [`message_data_with_sohm`] over any [`Storage`].
pub fn message_data_with_sohm_in<'a>(
file_data: &dyn Storage,
pub fn message_data_with_sohm_in<'a, S: Storage + ?Sized>(
file_data: &S,
msg: &'a crate::object_header::HeaderMessage,
offset_size: u8,
length_size: u8,
@@ -568,8 +568,8 @@ pub fn resolve_sohm_message(
}
/// [`resolve_sohm_message`] over any [`Storage`].
pub fn resolve_sohm_message_in(
file_data: &dyn Storage,
pub fn resolve_sohm_message_in<S: Storage + ?Sized>(
file_data: &S,
heap_id: &[u8; FHEAP_ID_LEN],
sohm_table: &SohmTable,
target_msg_type: MessageType,
@@ -603,12 +603,12 @@ pub fn message_data<'a>(
offset_size: u8,
length_size: u8,
) -> Result<Cow<'a, [u8]>, FormatError> {
message_data_in(&file_data, msg, offset_size, length_size)
message_data_in(file_data, msg, offset_size, length_size)
}
/// [`message_data`] over any [`Storage`].
pub fn message_data_in<'a>(
file_data: &dyn Storage,
pub fn message_data_in<'a, S: Storage + ?Sized>(
file_data: &S,
msg: &'a crate::object_header::HeaderMessage,
offset_size: u8,
length_size: u8,
@@ -650,8 +650,8 @@ pub fn resolve_shared_message(
}
/// [`resolve_shared_message`] over any [`Storage`].
pub fn resolve_shared_message_in(
file_data: &dyn Storage,
pub fn resolve_shared_message_in<S: Storage + ?Sized>(
file_data: &S,
shared_ref: &SharedMessageRef,
target_msg_type: MessageType,
offset_size: u8,
@@ -692,8 +692,8 @@ pub fn resolve_shared_message_with_sohm(
}
/// [`resolve_shared_message_with_sohm`] over any [`Storage`].
pub fn resolve_shared_message_with_sohm_in(
file_data: &dyn Storage,
pub fn resolve_shared_message_with_sohm_in<S: Storage + ?Sized>(
file_data: &S,
shared_ref: &SharedMessageRef,
target_msg_type: MessageType,
offset_size: u8,