Temporal Property Index (TPI)
The Temporal Property Index is HyperMesh DB’s primary storage structure. It is a read-optimised, immutable binary file pair that enables range queries over hyperedges to touch only the time buckets that overlap the query window.
On-disk layout
Section titled “On-disk layout”bucket_directory.bin┌──────────────────────────────────────────────────────────┐│ HmTpiHeader (magic + version + metadata) │├──────────────────────────────────────────────────────────┤│ BucketEntry[0] { start_ts, record_count, file_offset }││ BucketEntry[1] ... ││ ... ││ BucketEntry[B-1] │└──────────────────────────────────────────────────────────┘
hyperedges.bin┌──────────────────────────────────────────────────────────┐│ HmRecord[0] { event_ts, weight, mean_dist_m, ││ formation[16], member_count, ││ members[member_count] } ││ HmRecord[1] ... ││ ... │└──────────────────────────────────────────────────────────┘All integers are little-endian. Structs use __attribute__((packed)) to
eliminate compiler-inserted padding.
Query execution
Section titled “Query execution”A TPI range query for [T1, T2] proceeds in three steps:
-
Binary search the bucket directory for the first bucket with
start_ts >= T1. O(log B) comparisons on a ~700-byte file in L1 cache. -
Read only the buckets whose
[start_ts, start_ts + bucket_seconds)interval overlaps[T1, T2]. Eachpread()call fetches exactly the records in one bucket. -
Filter records: discard any whose
event_tsfalls outside[T1, T2](occurs only at the boundary buckets).
The result is then merged with matching WAL entries.
and returned sorted by event_ts.
Performance characteristics
Section titled “Performance characteristics”| Metric | Value (1,774-record, 86-bucket dataset) |
|---|---|
| Bucket directory size | ~700 B (fits in one cache line cluster) |
| Single-bucket read | ~1 pread() |
| Speedup vs full scan (1 % window) | ~86× |
| Median range query latency | < 500µs |
| P95 range query latency | < 2ms |
Compaction
Section titled “Compaction”After WAL entries accumulate (inserts + tombstones), the compact() operation:
- Reads all TPI records into memory.
- Reads all WAL entries.
- Applies:
final_set = (TPI ∪ WAL inserts) − WAL tombstones. - Re-sorts by
event_ts. - Re-partitions into buckets of
bucket_secondswidth. - Writes new
bucket_directory.binandhyperedges.bin. - Truncates
wal.binto zero entries. - Reopens the TPI + FMI readers.
Compaction is O(N log N) in the number of records and is designed to be idempotent — running it on an already-compacted database is a no-op.