Add memtable MultiGet finger search optimization#14428
Open
anand1976 wants to merge 4 commits intofacebook:mainfrom
Open
Add memtable MultiGet finger search optimization#14428anand1976 wants to merge 4 commits intofacebook:mainfrom
anand1976 wants to merge 4 commits intofacebook:mainfrom
Conversation
Implement finger search on skip list for memtable MultiGet. After each key lookup, the search path (splice) is cached and reused for the next key, reducing per-key cost from O(log N) to O(log d) where d is the distance between consecutive keys. Changes: - Add FindGreaterOrEqualWithFinger() and MultiGet() to InlineSkipList - Add virtual MultiGet() to MemTableRep, override in SkipListRep - Add memtable_multi_get_finger_search CF option (default: false) - Integrate finger search into MemTable::MultiGet when enabled - Add db_bench, db_stress, and crash test support - Add unit tests (InlineSkipList level) and integration tests (DB level) Benchmark results (2M keys in memtable, batch_size=64): - Baseline: ~265,700 ops/sec - Finger search: ~283,800 ops/sec - Improvement: ~7%
Optimize MultiGet by using a finger search on the memtable skip list. After finding key[i], the search path (Splice) is retained as a "finger" for key[i+1]. The next search walks up the finger until the forward pointer overshoots, then descends — costing O(log d) where d is the distance between consecutive sorted keys, rather than O(log n) from the head each time. Key changes: - Add InlineSkipList::FindGreaterOrEqualWithFinger() and MultiGet() with optional paranoid validation parameters (default off) - Add MemTableRep::MultiGet() virtual with validation support - Add SkipListRep::MultiGet() override delegating to skip list - Add MemTable::MultiGet() batched lookup phase that sorts keys, performs finger search, then unscrambles results - Rename option from memtable_multi_get_finger_search to memtable_batch_lookup_optimization - Add db_bench, db_stress, and crash test support - Add comprehensive unit tests including paranoid validation tests The optimization provides +3.6% to +10.1% throughput improvement on MultiGet benchmarks across various configurations.
Fix ASSERT_STATUS_CHECKED failure: wrap all list.MultiGet() calls in inlineskiplist_test.cc with ASSERT_OK() to check the returned Status, which is now non-void after the function deduplication.
|
@anand1976 has imported this pull request. If you are a Meta employee, you can view this in D95813786. |
- Value-initialize std::array declarations in memtable.cc to fix cppcoreguidelines-pro-type-member-init warnings - Add reserve() before push_back loop in inlineskiplist_test.cc to fix performance-inefficient-vector-operation warning - Add braces around single-statement for loop in db_basic_test.cc to fix readability-braces-around-statements warning
|
| Check | Count |
|---|---|
cert-err58-cpp |
1 |
concurrency-mt-unsafe |
1 |
| Total | 2 |
Details
db_stress_tool/db_stress_tool.cc (1 warning(s))
db_stress_tool/db_stress_tool.cc:279:7: warning: function is not thread safe [concurrency-mt-unsafe]
tools/ldb_cmd.cc (1 warning(s))
tools/ldb_cmd.cc:91:31: warning: initialization of 'ARG_UNIFORM_CV_THRESHOLD' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
|
@anand1976 has imported this pull request. If you are a Meta employee, you can view this in D95813786. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add memtable batch lookup optimization with finger search
Summary
Optimize memtable MultiGet by using a finger search on the skip list. After finding key[i], the search path (Splice) is retained as a "finger" for key[i+1]. The next search walks up the finger until the forward pointer overshoots, then descends -- costing O(log d) where d is the distance between consecutive sorted keys, rather than O(log N) from the head each time.
Controlled by the new
memtable_batch_lookup_optimizationcolumn family option (default: false).Changes
FindGreaterOrEqualWithFinger()andMultiGet()toInlineSkipListwith optional paranoid validation support (key ordering checks and per-key checksum verification via default parameters)MultiGet()toMemTableRep, override inSkipListRepmemtable_batch_lookup_optimizationCF optionMemTable::MultiGet-- sorts keys, performs batched finger search, then unscrambles resultsdb_bench,db_stress, and crash test supportInlineSkipList::MultiGet(5 tests) and integration tests at the DB level (25BatchLookuptests), including paranoid validation testsBenchmark Results
Setup: 2M keys in memtable, release build (
DEBUG_LEVEL=0).Single-threaded
multireadrandomMultithreaded
multireadrandom(batch_size=64)multireadwhilewriting(batch_size=64)No regression at any batch size or thread count. The finger is stack-allocated per
MultiGetcall, so there is no shared state or cache-line contention between threads. Concurrent writes don't invalidate the finger's bracket since it only reads via acquire-loadNext()pointers.Test Plan
make check-- all tests passASSERT_STATUS_CHECKED=1 make check-- all tests passdb_crashtest.py blackboxwith--memtable_batch_lookup_optimization=1-- passeddb_crashtest.py blackboxwith--memtable_batch_lookup_optimization=1 --paranoid_memory_checks=1-- passed