pub struct ColumnarEntityIndex { /* private fields */ }Expand description
Compact, sorted, binary-searched entity index. Columns are kept sorted by
ids (strictly ascending, unique) so Self::lookup can binary_search.
Invariants (upheld by every constructor):
ids.len() == starts.len() == lengths.len()idsis strictly ascending (hence unique)starts[i]/lengths[i]are the byte offset / byte length ofids[i], solookupreturns(start, start + length)to match the(start, end)tuple layout ofEntityIndex.
Implementations§
Source§impl ColumnarEntityIndex
impl ColumnarEntityIndex
Sourcepub fn from_columns(
ids: &[u32],
starts: &[u32],
lengths: &[u32],
) -> Result<Self, ColumnLengthMismatch>
pub fn from_columns( ids: &[u32], starts: &[u32], lengths: &[u32], ) -> Result<Self, ColumnLengthMismatch>
Build from the three delivered columns (setEntityIndex ingestion).
Verifies the id column’s ordering once, O(n): the pre-pass emits in
whatever order it iterates (its own FxHashMap iteration order is
arbitrary), so this cannot assume ascending. If the ids are already
strictly ascending the columns are used as-is (no sort); otherwise a
single stable argsort permutation is applied and duplicate ids are
collapsed last-in-input-order-wins.
Columns of unequal length are a ColumnLengthMismatch, checked before
any is read, so a malformed payload never panics a worker. Empty
columns are a valid, empty index.
Sourcepub fn from_owned_columns(
ids: Vec<u32>,
starts: Vec<u32>,
lengths: Vec<u32>,
) -> Result<Self, ColumnLengthMismatch>
pub fn from_owned_columns( ids: Vec<u32>, starts: Vec<u32>, lengths: Vec<u32>, ) -> Result<Self, ColumnLengthMismatch>
Consume binding-owned columns without another full allocation (#3989).
Validation and last-in-input-order duplicate precedence match from_columns.
Sourcepub fn from_hashmap_consuming(map: EntityIndex) -> Self
pub fn from_hashmap_consuming(map: EntityIndex) -> Self
Build from an already-scanned EntityIndex
hashmap, CONSUMING it. On the wasm prepass path the map is ~436 MB at
19.1 M entities and the conversion runs while the whole source file is
resident in the same <4 GiB heap; borrowing (from_hashmap) keeps the
map alive across the copy AND the sort, spiking ~970 MB of transients.
Consuming drains into one interleaved Vec<(id, start, len)> (~229 MB)
then sorts in place (sort_unstable; map keys are unique, so no
stability/permutation buffer). Peak during the drain is map + rows
capacity (~665 MB) until the map drops at end-of-loop; after that the
sort is in-place and the final column split briefly overlaps rows +
outputs (~458 MB) before rows drop. Still far below the borrowing path,
and the steady-state index is ~229 MB.
Sourcepub fn from_hashmap(map: &EntityIndex) -> Self
pub fn from_hashmap(map: &EntityIndex) -> Self
Build from an already-scanned EntityIndex
hashmap. The map is unique by construction (last-in-file-order-wins was
applied by HashMap::insert), so this only sorts the entries. Prefer
Self::from_hashmap_consuming when the map is no longer needed - it
avoids holding map + copies concurrently (P1 review finding on #1689).
Sourcepub fn from_scan<T>(content: &T) -> Self
pub fn from_scan<T>(content: &T) -> Self
Scan content and build the columns directly, replicating
crate::build_entity_index’s HEADER-skipping / quoted-string scan and
its last-in-file-order-wins duplicate handling — without ever
materializing the intermediate FxHashMap. Used by the wasm lazy
fallback when setEntityIndex was never called.
Reports the scanner’s #3395 refusals for the same reason
crate::build_entity_index does: this is a whole-file index build, so
a refused record is a record the model will not contain.