Skip to content

ht: fuse keys/values arrays into a single entries array (fixes #84) - #96

Merged
gg582 merged 1 commit into
mainfrom
perf/ht-fused-entries
Oct 4, 2026
Merged

gg582 merged 1 commit into
mainfrom
perf/ht-fused-entries

Conversation

@gg582

@gg582 gg582 commented Oct 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Fuses the separate keys/values backing arrays (and key_lens for the generic table) into a single fused entries array of {key, value} pairs in both ttak_map_t (include/ttak/ht/hash.h) and ttak_table_t (include/ttak/ht/table.h), keeping ctrls as a separate array so the probing logic is untouched.
  • A successful lookup now touches at most 2 cache lines (control byte + entry) instead of 3 (control byte + key line + value line).
  • Tombstone tracking from 80447e7 is preserved: delete still marks DELETED + bumps the tombstone count, insert reuses the first tombstone slot on the probe chain and decrements, and rehash-in-place/growth still clears tombstones by rebuilding from live entries only.
  • src/mem/mem.c iterations over the global ptr map read entries[i].key instead of keys[i].
  • Public API unchanged.

Benchmark

Random lookup throughput on a 1M-entry tt_map_t (capacity 2^21, ~50% load), 10M random lookups per rep, best-of-9 / median-of-9 reps, clock_gettime(CLOCK_MONOTONIC), same bench binary linked against the pre-change lib (95854ca) and the new lib:

build best ns/op median ns/op
old (separate keys/values) 805–816 818–838
new (fused entries) 789–793 795

~2% better best-case and ~4% better median lookup latency. The absolute numbers are inflated by per-call ttak_mem_access() overhead in the public map API; the structural cache-miss reduction (3→2 lines per hit) is the intended win and shows up consistently in best-case latency.

Full make test suite passes on the branch.

Not merged — leaving for review.

Replace the separate keys and values backing arrays in ttak_map_t and
ttak_table_t (keys/key_lens/values) with one fused entries array of
{key, value} pairs, keeping ctrls separate so probing logic is unchanged.
A successful lookup now touches at most two cache lines (ctrl byte +
entry) instead of three (ctrl byte + key line + value line).

Tombstone tracking from 80447e7 is preserved: deletes still mark slots
DELETED and bump the tombstone count, inserts reuse the first tombstone
slot on the probe chain and decrement, and rehash-in-place/growth still
clears tombstones by rebuilding from live entries only. The two mem.c
iterations over the global ptr map now read entries[i].key instead of
keys[i]. Public API is unchanged.
@gg582
gg582 merged commit a14eed7 into main Oct 4, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant