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:
@@ -171,13 +171,13 @@ pub fn read_superblock_extension(
|
||||
data: &[u8],
|
||||
sb: &Superblock,
|
||||
) -> Result<Option<SuperblockExtension>, FormatError> {
|
||||
read_superblock_extension_in(&data, sb)
|
||||
read_superblock_extension_in(data, sb)
|
||||
}
|
||||
|
||||
/// [`read_superblock_extension`] over any [`Storage`]; its length is the
|
||||
/// end of file.
|
||||
pub fn read_superblock_extension_in(
|
||||
file: &dyn Storage,
|
||||
pub fn read_superblock_extension_in<S: Storage + ?Sized>(
|
||||
file: &S,
|
||||
sb: &Superblock,
|
||||
) -> Result<Option<SuperblockExtension>, FormatError> {
|
||||
let os = sb.offset_size;
|
||||
@@ -351,12 +351,12 @@ impl CacheImage {
|
||||
location: CacheImageLocation,
|
||||
sb: &Superblock,
|
||||
) -> Result<Self, FormatError> {
|
||||
Self::decode_in(&data, location, sb)
|
||||
Self::decode_in(data, location, sb)
|
||||
}
|
||||
|
||||
/// [`Self::decode`] over any [`Storage`]: one read of the image block.
|
||||
pub fn decode_in(
|
||||
file: &dyn Storage,
|
||||
pub fn decode_in<S: Storage + ?Sized>(
|
||||
file: &S,
|
||||
location: CacheImageLocation,
|
||||
sb: &Superblock,
|
||||
) -> Result<Self, FormatError> {
|
||||
@@ -483,7 +483,10 @@ impl CacheImage {
|
||||
}
|
||||
|
||||
/// [`Self::block`] over any [`Storage`].
|
||||
pub fn block_in<'a>(&self, file: &'a dyn Storage) -> Result<Cow<'a, [u8]>, FormatError> {
|
||||
pub fn block_in<'a, S: Storage + ?Sized>(
|
||||
&self,
|
||||
file: &'a S,
|
||||
) -> Result<Cow<'a, [u8]>, FormatError> {
|
||||
image_block_in(file, self.location)
|
||||
}
|
||||
|
||||
@@ -511,8 +514,8 @@ fn image_block(data: &[u8], location: CacheImageLocation) -> Result<&[u8], Forma
|
||||
Ok(&data[start as usize..start as usize + len])
|
||||
}
|
||||
|
||||
fn image_block_in(
|
||||
file: &dyn Storage,
|
||||
fn image_block_in<S: Storage + ?Sized>(
|
||||
file: &S,
|
||||
location: CacheImageLocation,
|
||||
) -> Result<Cow<'_, [u8]>, FormatError> {
|
||||
let (start, len) = image_block_range(file.len(), location)?;
|
||||
@@ -540,12 +543,12 @@ fn image_block_range(
|
||||
/// ([`CacheImage::decode`]). `data` is the file from the superblock on, up
|
||||
/// to its recorded end of file.
|
||||
pub fn cache_image_state(data: &[u8], sb: &Superblock) -> Result<CacheImageState, FormatError> {
|
||||
cache_image_state_in(&data, sb)
|
||||
cache_image_state_in(data, sb)
|
||||
}
|
||||
|
||||
/// [`cache_image_state`] over any [`Storage`].
|
||||
pub fn cache_image_state_in(
|
||||
file: &dyn Storage,
|
||||
pub fn cache_image_state_in<S: Storage + ?Sized>(
|
||||
file: &S,
|
||||
sb: &Superblock,
|
||||
) -> Result<CacheImageState, FormatError> {
|
||||
match read_superblock_extension_in(file, sb)? {
|
||||
|
||||
Reference in New Issue
Block a user