db: mutation_cleaner: Enqueue new snapshots at the back
This fixes a quadratic behavior in case lots of snapshots with range
tombstones are queued for merging. Before the change, new snapshots
were inserted at the front, which is also where the worker looks
at. Merging a version has a linear component in complexity function
which depends on the number of range tombstones. If we merge snapshots
starting from the latest to oldest then the whole process becomes
quadratic because the version which is merged accumulates an
increasing amont of tombstones, ones which were already merged
before. We should instead merge starting from the oldest snapshots,
this way each tombstone is applied exactly once during merge.
This bug got wose after 4bd4aa2e88,
which makes merging tombstones more expensive.
Closes #10916
This commit is contained in:
committed by
Avi Kivity
parent
a8b02f7965
commit
3bb147ae95
@@ -17,7 +17,8 @@ class mutation_cleaner;
|
||||
|
||||
class mutation_cleaner_impl final {
|
||||
using snapshot_list = boost::intrusive::slist<partition_snapshot,
|
||||
boost::intrusive::member_hook<partition_snapshot, boost::intrusive::slist_member_hook<>, &partition_snapshot::_cleaner_hook>>;
|
||||
boost::intrusive::member_hook<partition_snapshot, boost::intrusive::slist_member_hook<>, &partition_snapshot::_cleaner_hook>,
|
||||
boost::intrusive::cache_last<true>>;
|
||||
struct worker {
|
||||
condition_variable cv;
|
||||
snapshot_list snapshots;
|
||||
@@ -90,7 +91,7 @@ void mutation_cleaner_impl::merge_and_destroy(partition_snapshot& ps) noexcept {
|
||||
// The snapshot must not be reachable by partitino_entry::read() after this,
|
||||
// which is ensured by slide_to_oldest() == stop_iteration::no.
|
||||
ps.migrate(&_region, _cleaner);
|
||||
_worker_state->snapshots.push_front(ps);
|
||||
_worker_state->snapshots.push_back(ps);
|
||||
_worker_state->cv.signal();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user