Expand description
Unit-based compaction picks for one TWCS window.
Picks select a contiguous interval of units in a fixed order. Grouping prefers rewriting related files together, but input limits and fallback paths may split groups or use single-file units. Separate admission checks preserve each pick’s progress guarantees under the assumptions below.
pick_active_l1reduces the L1 file count of the active window.pick_small_l1reduces small L1 files without rewriting large peers.pick_closed_mergeonly merges intervals of an inactive window whose outputs cannot add conflicts. Compaction outputs stay inside the bounding box of the inputs, so they can only overlap files intruding on that box.
When a window’s split-unit conflict graph is too dense to materialize,
pick_closed_merge falls back to a bounded file reduction and admits it
only when the same conflict bound holds.
§Termination
Let P be the number of conflicting file pairs (Extent::conflicts) in an
inactive window and N its file count. A merge removes every pair among its
inputs. Its outputs are one sorted run with no internal conflicts,
so they only conflict with the I files intruding on the inputs’ box, at
most outputs · I pairs. An inactive pick only merges inputs that had at
least as many pairs with other files, so P does not grow; without
intruders the inputs are closed and add no pairs. Every inactive pick either
resolves a pair (P drops) or removes a file (P does not grow and N
drops), so (P, N) strictly decreases in lexicographic order until the
window receives new writes. Active-window picks may add conflicts, so each
of them must remove a file: N strictly decreases.
The argument relies on how the compactor writes outputs:
- Outputs hold a subset of the input rows, so each output’s time and key bounds lie inside the inputs’ bounding box.
- Outputs are one stream in (key, time) order. For regions with a primary
key, the writer only splits between complete series, so output key ranges
are disjoint. Without a primary key, outputs have disjoint or touching
time ranges. Neither is an
Extent::conflictspair. - A split only starts a new file once the current one reaches the size
threshold, and outputs are not larger than inputs in total, so
PickLimits::predicted_outputsbounds the output count.
test_closed_merges_terminate and test_active_l1_picks_terminate replay
random windows with outputs written under these rules.
Structs§
- Closed
Merge 🔒Candidate - A scored interval retained until the best candidate(s) are materialized.
- Closed
Merge 🔒Options - Thresholds of the closed merge pick.
- Disjoint
Set 🔒 - Union-find over file indices; each root is the smallest index of its set.
- Extent 🔒
- Time and primary key bounds of a file or a group of files.
- Extent
Index 🔒 - Files of a window ordered by their lower primary key, in a segment tree holding the bounds of each subtree.
- Interval
Stats 🔒 - Totals of a contiguous interval of units.
- Pick
Limits 🔒 - Output size limits and input limits shared by both picks.
- Subtree
Bounds 🔒 - Key and time bounds of the files in a subtree of
ExtentIndex. - Unit 🔒
- Files that are compacted together.
- Unit
Pick 🔒 - A selected compaction input.
Enums§
- Upper
Key 🔒 - Upper primary key bound, ordered after every key when unknown.
Constants§
- CONFLICT_
GRAPH_ 🔒BUDGET - Maximum number of index nodes visited while building conflict structures for a pick. Above this, the picker falls back to a bounded file reduction instead of materializing an unbounded conflict graph.
- MAX_
REWRITE_ 🔒FILES_ PER_ REDUCED_ FILE - An L1 file reduction may rewrite at most this many output files’ worth of bytes per SST it removes.
- SMALL_
L1_ 🔒SIZE_ FACTOR - A small L1 file occupies at most one quarter of the output size budget.
Functions§
- adds_
no_ 🔒conflicts - Whether merging
unitsintooutputsfiles adds no more conflicts than their files have with other files. Outputs stay inside the bounding box of the inputs, so each of them may conflict with every file intruding on that box. An interval without intruders is closed and adds no conflicts. - close_
units 🔒 - Merges units until no file intrudes on a unit it does not belong to.
- collect_
inputs 🔒 - conflict_
units 🔒 - Groups files into connected components of
Extent::conflicts, each with its number of conflicting pairs. Each file only checks the files the index finds near it: O((N + M) log N) for M pairs of files whose key and time ranges meet. - extents_
of 🔒 - for_
each_ 🔒interval - Visits every contiguous interval of units with at most
max_input_filesfiles: O(U · K) intervals for an input limit K. Each interval counts the conflicts of its split files fromsplit_conflicts(seesplit_conflicts) with a binary search; an emptysplit_conflictsskips them. - has_
balanced_ 🔒components - Whether every group of conflicting files among
unitsis balanced, seehas_balanced_runs. Runs of separate groups never overlap, so pairing a dominant run with the peer of another group would hide it. Takes O(K²) conflict checks for K files. - has_
balanced_ 🔒runs - Whether the largest sorted run among
filesholds at mosttolerancebytes more than all other runs together. Runs are built greedily in time order, which takes O(K²) conflict checks for K files. - interval_
stats_ 🔒exact - Totals of an interval without materializing
split_conflicts. - is_
admissible_ 🔒dense_ interval - File reduction and rewrite limits are checked by the interval picker; each dense candidate must also respect the closed-window conflict policy.
- is_
more_ 🔒efficient - Whether
benefitpersizebytes beats the best so far; ties prefer fewer bytes, then the earlier interval. - is_
single_ 🔒key - pick_
active_ 🔒l1 - Picks L1 files of the active window whose compaction removes files.
- pick_
active_ 🔒l1_ with_ budget pick_active_l1with an explicit work budget, so tests can exercise the single-file fallback without a window-sized conflict graph.- pick_
closed_ 🔒merge - Picks an interval of units among all files of an inactive window.
- pick_
closed_ 🔒merge_ by_ class - Discovers file reduction and overlap resolution together, sharing both the conflict graph and interval traversal. The first slot is file reduction.
- pick_
closed_ 🔒merge_ candidates - pick_
closed_ 🔒merge_ with_ budget pick_closed_mergewith an explicit work budget, so tests can exercise the dense fallback without building a window-sized conflict graph.- pick_
dense_ 🔒closed_ merge - Picks a bounded file reduction when the split-unit conflict graph is too dense to materialize.
- pick_
reducing_ 🔒interval - Picks the interval of
unitsthat removes the most files within the rewrite budget, then rewrites the fewest bytes. - pick_
reducing_ 🔒interval_ where - Selects a reducing interval of sorted units, with an additional filter so the dense fallback can retry without duplicating the reduction guards.
- pick_
small_ 🔒l1 - Reduces small L1 files left behind by a closed merge, including in settling windows. The input bytes fit in one output and no input dominates its peers, so each merge removes files without repeatedly rewriting an accumulator.
- single_
file_ 🔒units - Treats every file as its own split unit, for the dense fallback that cannot afford to build conflict components.
- sort_
units 🔒 - Orders units by minimum primary key, then by time, so adjacent units are key-adjacent. Compaction outputs and time-sliced flushes split a window by key ranges, so merging neighbors in this order keeps outputs from covering the key ranges of files left behind.
- split_
conflicts 🔒 - Positions of the split units each unit conflicts with, sorted. Files of different units never conflict, so only split files have any.
- split_
oversized_ 🔒units - Replaces units with more files than one compaction accepts by single files, which are no longer closed.