Replies: 3 comments 3 replies
-
|
Hi, we were thinking about this when we merged together offset and timestamp indexes into singular structure and we've found that this does not scale really well with huge partition count. Our indexes aren't sparse, which means we store them per message, rather than per N messages (batch), thus the memory overhead will be pretty big. We are not concerned about cache misses, as our indexes are cached in memory per segment and since they are iterated through fairly frequently, the odds of a cache miss are fairly small (didn't measure this yet, as we are not at this stage of optimization). Also you've mentioned binary search, which we use already and afaik binary search isn't the most cache friendly searching algorithm, unless you use something like eytzinger layout, which we don't want to use as it adds a lot of complexity and it doesn't work really well with dynamically sized containers since everytime the collection has to scale up, it has to be reallocated and copied over, constructing eytzinger layout array is very expensive. |
Beta Was this translation helpful? Give feedback.
-
|
Just to add: if we have open segment, we store indexes in memory. Each index points to a single message. There is no binary search when getting messages from open segment by offset. This is O(1) operation because index of index is relative offset of message in segment. The only binary search that could happen is during fetch messages by timestamp, but that's another story, IMHO not worth optimizing at this point. |
Beta Was this translation helpful? Give feedback.
-
|
Just to clarify: the optimization isn’t about binary search at all — that keeps coming up, (AM I READING IT WRONG?) but it’s not the target. The gain comes from improving the memory layout, which affects every path: O(1) open-segment lookups, sequential scans, timestamp lookups, compaction, replication, everything. Even with O(1) access, if an entry spans multiple cache lines or its hot fields aren’t contiguous, the CPU still pays extra memory loads. So the proposal isn’t changing algorithms — it’s simply making each access cheaper at the hardware level. Whether the search is O(1), O(log N), or a scan doesn’t matter; cacheline efficiency is orthogonal. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
storage: add compact IndexEntryDense for cache-friendly in-memory segment index
Summary / Motivation
Segment index lookups (mapping offsets to file positions or timestamps) are a hot path in Iggy’s read performance. Currently, the in-memory representation of index entries may be scattered or pointer-heavy, causing:
Proposal: Introduce a dense, cache-line-aligned in-memory representation for segment index entries (IndexEntryDense) that:
Is optional / opt-in — existing code paths continue to work, enabling gradual integration.
Design / Implementation Details
IndexEntryDense is a #[repr(C, align(64))] struct:
Benefits / Expected Impact
Testing & Benchmarking Plan
System-level tests: run server under read-heavy load; measure cache misses and CPU cycles:
Next Steps / Future Work
If this PR yields measurable improvement, the dense, cache-line-friendly pattern can be applied to other hot paths:
These can be stacked for cumulative performance gains without altering on-disk formats.
Summary
This PR provides a small, safe, and measurable in-memory optimization that reduces cache-miss overhead on segment index lookups.
Disk format remains unchanged.
Opt-in design allows gradual adoption.
Lays groundwork for further cache-friendly optimizations in the future.
Beta Was this translation helpful? Give feedback.
All reactions