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 atf2ff2c4so it builds there for an A/B. Provisional A/B againstf2ff2c4(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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user