Finding one link or attribute by name read every entry: Group::dataset and Group::group (File, MmapFile, LazyFile) listed the whole group per call, and path resolution scanned each group's links. Opening every child of a 35 001-link group by name decoded ~1.2e9 links. Now a dense group's v2 B-tree name index (type 5, lookup3 hash of the name) is descended to the records with the name's hash (btree_v2::find_btree_v2_records reads only the nodes whose key interval overlaps), and only those links are read and compared; all hash-equal records are compared, so libhdf5's tie order does not matter. Dense attributes the same through their type 8 index (attribute::find_attribute_in_file, facade attr(name)); huge heap objects through their ID-ordered index. group_v2::resolve_child returns what the listing has under a name (soft links followed, dangling/external ones not found). Group::entries and File::group_at hand out a listing's addresses. The lookup-stats feature counts heap objects read. Tests: one lookup in an h5py-written 35 001-link group with colliding hashes reads at most two links (before: 35 001, failing), attribute lookups likewise (before: 3 000, failing), every child opens through all three readers and matches h5py, every link kind resolves as h5py resolves it in dense and compact groups, 300 huge attributes are found, and a range search matches a full scan at every tree depth. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
32 lines
1.0 KiB
Rust
32 lines
1.0 KiB
Rust
//! Work counters for tests of lookup cost (feature `lookup-stats`).
|
|
//!
|
|
//! Counts fractal-heap objects read — each is one link or attribute message
|
|
//! decoded out of a dense group or dense attribute storage — so a test can
|
|
//! check that finding one name reads a handful of them, not the whole group.
|
|
//! Per thread, so tests running in parallel do not see each other's reads.
|
|
//! Without the feature the counting compiles to nothing.
|
|
|
|
#[cfg(feature = "lookup-stats")]
|
|
std::thread_local! {
|
|
static HEAP_OBJECTS: core::cell::Cell<u64> = const { core::cell::Cell::new(0) };
|
|
}
|
|
|
|
/// Record one heap object read.
|
|
#[inline(always)]
|
|
pub(crate) fn heap_object_read() {
|
|
#[cfg(feature = "lookup-stats")]
|
|
HEAP_OBJECTS.with(|c| c.set(c.get() + 1));
|
|
}
|
|
|
|
/// Heap objects read on this thread since the last [`reset`].
|
|
#[cfg(feature = "lookup-stats")]
|
|
pub fn heap_objects_read() -> u64 {
|
|
HEAP_OBJECTS.with(core::cell::Cell::get)
|
|
}
|
|
|
|
/// Zero this thread's counters.
|
|
#[cfg(feature = "lookup-stats")]
|
|
pub fn reset() {
|
|
HEAP_OBJECTS.with(|c| c.set(0));
|
|
}
|