Skip to content

Commit adb9bf5

Browse files
committed
Fix max_successive_merges counting CPU overhead regression (#12546)
Summary: In #12365 we made `max_successive_merges` non-strict by default. Before #12365, `CountSuccessiveMergeEntries()`'s scan was implicitly limited to `max_successive_merges` entries for a given key, because after that the merge operator would be invoked and the merge chain would be collapsed. After #12365, the merge chain will not be collapsed no matter how long it is when the chain's operands are not all in memory. Since `CountSuccessiveMergeEntries()` scanned the whole merge chain, #12365 had a side effect that it would scan more memtable entries. This PR introduces a limit so it won't scan more entries than it could before. Pull Request resolved: #12546 Reviewed By: jaykorean Differential Revision: D56193693 Pulled By: ajkr fbshipit-source-id: b070ba0703ef733e0ff230f89cd5cca5233b84da
1 parent 7dd5e91 commit adb9bf5

File tree

4 files changed

+12
-7
lines changed

4 files changed

+12
-7
lines changed

db/memtable.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -1621,7 +1621,8 @@ Status MemTable::UpdateCallback(SequenceNumber seq, const Slice& key,
16211621
return Status::NotFound();
16221622
}
16231623

1624-
size_t MemTable::CountSuccessiveMergeEntries(const LookupKey& key) {
1624+
size_t MemTable::CountSuccessiveMergeEntries(const LookupKey& key,
1625+
size_t limit) {
16251626
Slice memkey = key.memtable_key();
16261627

16271628
// A total ordered iterator is costly for some memtablerep (prefix aware
@@ -1633,7 +1634,7 @@ size_t MemTable::CountSuccessiveMergeEntries(const LookupKey& key) {
16331634

16341635
size_t num_successive_merges = 0;
16351636

1636-
for (; iter->Valid(); iter->Next()) {
1637+
for (; iter->Valid() && num_successive_merges < limit; iter->Next()) {
16371638
const char* entry = iter->key();
16381639
uint32_t key_length = 0;
16391640
const char* iter_key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);

db/memtable.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,10 @@ class MemTable {
326326
const ProtectionInfoKVOS64* kv_prot_info);
327327

328328
// Returns the number of successive merge entries starting from the newest
329-
// entry for the key up to the last non-merge entry or last entry for the
330-
// key in the memtable.
331-
size_t CountSuccessiveMergeEntries(const LookupKey& key);
329+
// entry for the key. The count ends when the oldest entry in the memtable
330+
// with which the newest entry would be merged is reached, or the count
331+
// reaches `limit`.
332+
size_t CountSuccessiveMergeEntries(const LookupKey& key, size_t limit);
332333

333334
// Update counters and flush status after inserting a whole write batch
334335
// Used in concurrent memtable inserts.

db/write_batch.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -2623,8 +2623,10 @@ class MemTableInserter : public WriteBatch::Handler {
26232623
LookupKey lkey(key, sequence_);
26242624

26252625
// Count the number of successive merges at the head
2626-
// of the key in the memtable
2627-
size_t num_merges = mem->CountSuccessiveMergeEntries(lkey);
2626+
// of the key in the memtable. Limit the count to the threshold for
2627+
// triggering merge to prevent unnecessary counting overhead.
2628+
size_t num_merges = mem->CountSuccessiveMergeEntries(
2629+
lkey, moptions->max_successive_merges /* limit */);
26282630

26292631
if (num_merges >= moptions->max_successive_merges) {
26302632
perform_merge = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* Fixed a regression when `ColumnFamilyOptions::max_successive_merges > 0` where the CPU overhead for deciding whether to merge could have increased unless the user had set the option `ColumnFamilyOptions::strict_max_successive_merges`

0 commit comments

Comments
 (0)