Cross-cutting data-structure rewrite tracked under #537.
Current state
Field names are kept as String everywhere on the hot path:
laurus/src/lexical/index/inverted/writer.rs:59: fields: HashMap<String, FieldOption>.
laurus/src/lexical/index/inverted/writer.rs:621: format!("{field}:{term}") per token.
laurus/src/vector/index/quantized_storage.rs:45: field_index: HashMap<String, Arc<HashMap<u64, u32>>>.
laurus/src/vector/index/hnsw/reader.rs:64,560: prefetch_index: HashMap<String, _>, vector_ids: Vec<(u64, String)>.
- Per-vector
field_name UTF-8 inline in segment records (quantized_io.rs:14-23).
Typical schemas have 1-10 fields per index; the String cost on every probe is pure waste.
Proposed direction
- Introduce
FieldId(u16) and FieldRegistry { id_by_name: AHashMap<String, FieldId>, names: Vec<String> } at segment/index open.
- Lexical writer:
Vec<(SmolStr, FieldOption)> indexed by FieldId.
- Vector storage pools:
SmallVec<[Arc<DocIdMap>; 4]> indexed by FieldId.0 as usize.
- Per-segment field dictionary on disk (one string per id, varint-coded) so per-record payload references field by id only.
String field names retained only at the public API boundary.
Acceptance
- Lexical writer hot path no longer calls
format!.
- Vector storage records drop the inline
field_name UTF-8 (replaced by field_id: u16).
- Per-query hashing on field name eliminated in HNSW/Flat/IVF search paths.
References
- Lucene
FieldInfos (interns to int fieldNumber).
- Tantivy
FieldId(u32).
- Qdrant payload schema ids.
Cross-cutting data-structure rewrite tracked under #537.
Current state
Field names are kept as
Stringeverywhere on the hot path:laurus/src/lexical/index/inverted/writer.rs:59:fields: HashMap<String, FieldOption>.laurus/src/lexical/index/inverted/writer.rs:621:format!("{field}:{term}")per token.laurus/src/vector/index/quantized_storage.rs:45:field_index: HashMap<String, Arc<HashMap<u64, u32>>>.laurus/src/vector/index/hnsw/reader.rs:64,560:prefetch_index: HashMap<String, _>,vector_ids: Vec<(u64, String)>.field_nameUTF-8 inline in segment records (quantized_io.rs:14-23).Typical schemas have 1-10 fields per index; the
Stringcost on every probe is pure waste.Proposed direction
FieldId(u16)andFieldRegistry { id_by_name: AHashMap<String, FieldId>, names: Vec<String> }at segment/index open.Vec<(SmolStr, FieldOption)>indexed byFieldId.SmallVec<[Arc<DocIdMap>; 4]>indexed byFieldId.0 as usize.Stringfield names retained only at the public API boundary.Acceptance
format!.field_name UTF-8(replaced byfield_id: u16).References
FieldInfos(interns toint fieldNumber).FieldId(u32).