Skip to content

Commit e62a303

Browse files
ever0deRaduBerinde
authored andcommitted
compact: make TombstoneDenseCompactionThreshold dynamically reconfigurable
Previously, TombstoneDenseCompactionThreshold was a static float64 value that could only be set at initialization time. This made it impossible to dynamically adjust the threshold based on changing workload characteristics or operational requirements. This commit changes TombstoneDenseCompactionThreshold from a float64 to a function returning float64, following the pattern used by other dynamic options like CompactionGarbageFractionForMaxConcurrency and VirtualTableRewriteUnreferencedFraction. The default value remains 0.10. Benefits: - Allows runtime adjustment of tombstone compaction behavior - Enables workload-specific tuning without restarting the database - Makes it easier to turn down or disable tombstone compactions when they lead to increased resource usage with no visible latency benefits Changes: - Updated Options.Experimental.TombstoneDenseCompactionThreshold to func() float64 - Modified EnsureDefaults to use function wrapper - Updated String() and Parse() methods to handle function type - Modified pickTombstoneDensityCompaction to call the function - Updated all test files to use function syntax Fixes #5457.
1 parent 3dd8e6f commit e62a303

File tree

4 files changed

+25
-18
lines changed

4 files changed

+25
-18
lines changed

compaction_picker.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,8 @@ func (p *compactionPickerByScore) pickBlobFileRewriteCandidate(
18271827
func (p *compactionPickerByScore) pickTombstoneDensityCompaction(
18281828
env compactionEnv,
18291829
) (pc *pickedTableCompaction) {
1830-
if p.opts.Experimental.TombstoneDenseCompactionThreshold <= 0 {
1830+
threshold := p.opts.Experimental.TombstoneDenseCompactionThreshold()
1831+
if threshold <= 0 {
18311832
// Tombstone density compactions are disabled.
18321833
return nil
18331834
}
@@ -1855,7 +1856,7 @@ func (p *compactionPickerByScore) pickTombstoneDensityCompaction(
18551856
if !propsValid {
18561857
continue
18571858
}
1858-
if props.TombstoneDenseBlocksRatio < p.opts.Experimental.TombstoneDenseCompactionThreshold {
1859+
if props.TombstoneDenseBlocksRatio < threshold {
18591860
continue
18601861
}
18611862
overlaps := p.vers.Overlaps(lastNonEmptyLevel, f.UserKeyBounds())

compaction_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3507,7 +3507,7 @@ func TestTombstoneDensityCompactionMoveOptimization(t *testing.T) {
35073507
)
35083508

35093509
opts := DefaultOptions()
3510-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.5 // Lower for test
3510+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.5 } // Lower for test
35113511
opts.Experimental.NumDeletionsThreshold = 1
35123512
opts.Experimental.CompactionScheduler = func() CompactionScheduler {
35133513
return NewConcurrencyLimitSchedulerWithNoPeriodicGrantingForTest()
@@ -3609,7 +3609,7 @@ func TestTombstoneDensityCompactionMoveOptimization_NoMoveWithOverlap(t *testing
36093609
)
36103610

36113611
opts := DefaultOptions()
3612-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.5 // Lower for test
3612+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.5 } // Lower for test
36133613
opts.Experimental.NumDeletionsThreshold = 1
36143614
opts.Experimental.CompactionScheduler = func() CompactionScheduler {
36153615
return NewConcurrencyLimitSchedulerWithNoPeriodicGrantingForTest()
@@ -3693,7 +3693,7 @@ func TestTombstoneDensityCompactionMoveOptimization_GrandparentOverlapTooLarge(t
36933693
)
36943694

36953695
opts := DefaultOptions()
3696-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.5
3696+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.5 }
36973697
opts.Experimental.NumDeletionsThreshold = 1
36983698
opts.Experimental.CompactionScheduler = func() CompactionScheduler {
36993699
return NewConcurrencyLimitSchedulerWithNoPeriodicGrantingForTest()
@@ -3761,7 +3761,7 @@ func TestTombstoneDensityCompactionMoveOptimization_BelowDensityThreshold(t *tes
37613761
)
37623762

37633763
opts := DefaultOptions()
3764-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.9 // Set high threshold
3764+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.9 } // Set high threshold
37653765
opts.Experimental.NumDeletionsThreshold = 1
37663766
opts.Experimental.CompactionScheduler = func() CompactionScheduler {
37673767
return NewConcurrencyLimitSchedulerWithNoPeriodicGrantingForTest()
@@ -3813,7 +3813,7 @@ func TestTombstoneDensityCompactionMoveOptimization_InvalidStats(t *testing.T) {
38133813
)
38143814

38153815
opts := DefaultOptions()
3816-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.5
3816+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.5 }
38173817
opts.Experimental.NumDeletionsThreshold = 1
38183818
opts.Experimental.CompactionScheduler = func() CompactionScheduler {
38193819
return NewConcurrencyLimitSchedulerWithNoPeriodicGrantingForTest()

options.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -695,17 +695,19 @@ type Options struct {
695695
// sstable writers. The default value is 0.5.
696696
DeletionSizeRatioThreshold float32
697697

698-
// TombstoneDenseCompactionThreshold is the minimum percent of data
699-
// blocks in a table that must be tombstone-dense for that table to be
700-
// eligible for a tombstone density compaction. It should be defined as a
701-
// ratio out of 1. The default value is 0.10.
698+
// TombstoneDenseCompactionThreshold is a function that returns the minimum
699+
// percent of data blocks in a table that must be tombstone-dense for that
700+
// table to be eligible for a tombstone density compaction. The value should
701+
// be defined as a ratio out of 1. The default value is 0.10.
702702
//
703703
// If multiple tables are eligible for a tombstone density compaction, then
704704
// tables with a higher percent of tombstone-dense blocks are still
705705
// prioritized for compaction.
706706
//
707-
// A zero or negative value disables tombstone density compactions.
708-
TombstoneDenseCompactionThreshold float64
707+
// Using a function allows for dynamic reconfiguration of the threshold based
708+
// on workload characteristics. A zero or negative value disables tombstone
709+
// density compactions.
710+
TombstoneDenseCompactionThreshold func() float64
709711

710712
// FileCacheShards is the number of shards per file cache.
711713
// Reducing the value can reduce the number of idle goroutines per DB
@@ -1672,8 +1674,8 @@ func (o *Options) EnsureDefaults() {
16721674
if o.Experimental.DeletionSizeRatioThreshold == 0 {
16731675
o.Experimental.DeletionSizeRatioThreshold = sstable.DefaultDeletionSizeRatioThreshold
16741676
}
1675-
if o.Experimental.TombstoneDenseCompactionThreshold == 0 {
1676-
o.Experimental.TombstoneDenseCompactionThreshold = 0.10
1677+
if o.Experimental.TombstoneDenseCompactionThreshold == nil {
1678+
o.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.10 }
16771679
}
16781680
if o.Experimental.FileCacheShards <= 0 {
16791681
o.Experimental.FileCacheShards = runtime.GOMAXPROCS(0)
@@ -1821,7 +1823,7 @@ func (o *Options) String() string {
18211823
fmt.Fprintf(&buf, " read_sampling_multiplier=%d\n", o.Experimental.ReadSamplingMultiplier)
18221824
fmt.Fprintf(&buf, " num_deletions_threshold=%d\n", o.Experimental.NumDeletionsThreshold)
18231825
fmt.Fprintf(&buf, " deletion_size_ratio_threshold=%f\n", o.Experimental.DeletionSizeRatioThreshold)
1824-
fmt.Fprintf(&buf, " tombstone_dense_compaction_threshold=%f\n", o.Experimental.TombstoneDenseCompactionThreshold)
1826+
fmt.Fprintf(&buf, " tombstone_dense_compaction_threshold=%f\n", o.Experimental.TombstoneDenseCompactionThreshold())
18251827
// We no longer care about strict_wal_tail, but set it to true in case an
18261828
// older version reads the options.
18271829
fmt.Fprintf(&buf, " strict_wal_tail=%t\n", true)
@@ -2257,7 +2259,11 @@ func (o *Options) Parse(s string, hooks *ParseHooks) error {
22572259
o.Experimental.DeletionSizeRatioThreshold = float32(val)
22582260
err = parseErr
22592261
case "tombstone_dense_compaction_threshold":
2260-
o.Experimental.TombstoneDenseCompactionThreshold, err = strconv.ParseFloat(value, 64)
2262+
var threshold float64
2263+
threshold, err = strconv.ParseFloat(value, 64)
2264+
if err == nil {
2265+
o.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return threshold }
2266+
}
22612267
case "table_cache_shards":
22622268
o.Experimental.FileCacheShards, err = strconv.Atoi(value)
22632269
case "table_format":

options_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ func TestOptionsParse(t *testing.T) {
406406
opts.Experimental.ReadSamplingMultiplier = 400
407407
opts.Experimental.NumDeletionsThreshold = 500
408408
opts.Experimental.DeletionSizeRatioThreshold = 0.7
409-
opts.Experimental.TombstoneDenseCompactionThreshold = 0.2
409+
opts.Experimental.TombstoneDenseCompactionThreshold = func() float64 { return 0.2 }
410410
opts.Experimental.FileCacheShards = 500
411411
opts.Experimental.SecondaryCacheSizeBytes = 1024
412412
opts.Experimental.ValueSeparationPolicy = func() ValueSeparationPolicy {

0 commit comments

Comments
 (0)