From 8c61bce9448091c743d1e078b5f22fab01fde64f Mon Sep 17 00:00:00 2001 From: devanbenz Date: Tue, 4 Mar 2025 12:06:48 -0600 Subject: [PATCH 1/9] feat: Add CompactPointsPerBlock config opt This PR adds an additional parameter for influxd CompactPointsPerBlock. It adjusts the DefaultAggressiveMaxPointsPerBlock to 10,000. We had discovered that with the points per block set to 100,000 compacted TSM files were increasing. After modifying the points per block to 10,000 we noticed that the file sizes decreased. The value has been set as a parameter that can be adjusted by administrators this allows there to be some tuning if compression problems are encountered. --- tsdb/config.go | 8 +++--- tsdb/engine/tsm1/compact.go | 2 +- tsdb/engine/tsm1/compact_test.go | 42 ++++++++++++++++---------------- tsdb/engine/tsm1/engine.go | 6 ++--- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/tsdb/config.go b/tsdb/config.go index 0490934f1bb..675194e80a2 100644 --- a/tsdb/config.go +++ b/tsdb/config.go @@ -52,9 +52,9 @@ const ( // block in a TSM file DefaultMaxPointsPerBlock = 1000 - // AggressiveMaxPointsPerBlock is used when we want to further compact blocks + // DefaultAggressiveMaxPointsPerBlock is used when we want to further compact blocks // it is 100 times the default amount of points we use per block - AggressiveMaxPointsPerBlock = DefaultMaxPointsPerBlock * 100 + DefaultAggressiveMaxPointsPerBlock = DefaultMaxPointsPerBlock * 10 // DefaultMaxSeriesPerDatabase is the maximum number of series a node can hold per database. // This limit only applies to the "inmem" index. @@ -92,7 +92,7 @@ var SingleGenerationReasonText string = SingleGenerationReason() // when checked for full compaction. // 1048576000 is a magic number for bytes per gigabyte. func SingleGenerationReason() string { - return fmt.Sprintf("not fully compacted and not idle because single generation with more than 2 files under %d GB and more than 1 file(s) under aggressive compaction points per block count (%d points)", int(MaxTSMFileSize/1048576000), AggressiveMaxPointsPerBlock) + return fmt.Sprintf("not fully compacted and not idle because single generation with more than 2 files under %d GB and more than 1 file(s) under aggressive compaction points per block count (%d points)", int(MaxTSMFileSize/1048576000), DefaultAggressiveMaxPointsPerBlock) } // Config holds the configuration for the tsbd package. @@ -128,6 +128,7 @@ type Config struct { CompactFullWriteColdDuration toml.Duration `toml:"compact-full-write-cold-duration"` CompactThroughput toml.Size `toml:"compact-throughput"` CompactThroughputBurst toml.Size `toml:"compact-throughput-burst"` + CompactPointsPerBlock toml.Size `toml:"compact-points-per-block"` // Options for ingress metrics IngressMetricByMeasurement bool `toml:"ingress-metric-by-measurement-enabled"` @@ -197,6 +198,7 @@ func NewConfig() Config { CompactFullWriteColdDuration: toml.Duration(DefaultCompactFullWriteColdDuration), CompactThroughput: toml.Size(DefaultCompactThroughput), CompactThroughputBurst: toml.Size(DefaultCompactThroughputBurst), + CompactPointsPerBlock: toml.Size(DefaultAggressiveMaxPointsPerBlock), MaxSeriesPerDatabase: DefaultMaxSeriesPerDatabase, MaxValuesPerTag: DefaultMaxValuesPerTag, diff --git a/tsdb/engine/tsm1/compact.go b/tsdb/engine/tsm1/compact.go index bcb03598119..5512786fd15 100644 --- a/tsdb/engine/tsm1/compact.go +++ b/tsdb/engine/tsm1/compact.go @@ -253,7 +253,7 @@ func (c *DefaultPlanner) FullyCompacted() (bool, string) { aggressivePointsPerBlockCount := 0 filesUnderMaxTsmSizeCount := 0 for _, tsmFile := range gens[0].files { - if c.FileStore.BlockCount(tsmFile.Path, 1) >= tsdb.AggressiveMaxPointsPerBlock { + if c.FileStore.BlockCount(tsmFile.Path, 1) >= tsdb.DefaultAggressiveMaxPointsPerBlock { aggressivePointsPerBlockCount++ } if tsmFile.Size < tsdb.MaxTSMFileSize { diff --git a/tsdb/engine/tsm1/compact_test.go b/tsdb/engine/tsm1/compact_test.go index 578a63c8a42..04dcf3828f7 100644 --- a/tsdb/engine/tsm1/compact_test.go +++ b/tsdb/engine/tsm1/compact_test.go @@ -2400,7 +2400,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { // > 2 GB total group size // 50% of files are at aggressive max block size { - "Small group size with single generation 50% at DefaultMaxPointsPerBlock and 50% at AggressiveMaxPointsPerBlock", + "Small group size with single generation 50% at DefaultMaxPointsPerBlock and 50% at DefaultAggressiveMaxPointsPerBlock", []tsm1.FileStat{ { Path: "01-05.tsm1", @@ -2436,10 +2436,10 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, @@ -2464,7 +2464,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { Size: 450 * 1024 * 1024, }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, }, @@ -2582,16 +2582,16 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { Size: 400 * 1024 * 1024, }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, @@ -2674,7 +2674,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { // This test is added to account for a single generation that has a group size // over 2 GB with 1 file under 2 GB all at max points per block with aggressive compaction. // It should not compact any further. - "TSM files at AggressiveMaxPointsPerBlock", + "TSM files at DefaultAggressiveMaxPointsPerBlock", []tsm1.FileStat{ { Path: "01-13.tsm1", @@ -2685,8 +2685,8 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { Size: 691 * 1024 * 1024, }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, }, "", 0, }, { @@ -2705,7 +2705,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { Size: 691 * 1024 * 1024, }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, tsdb.DefaultMaxPointsPerBlock, }, "", @@ -2714,7 +2714,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { { // This test is added to account for a single generation that has a group size // over 2 GB and multiple files under 2 GB all at max points per block for aggressive compaction. - "Group size over 2 with multiple files under 2GB and at AggressiveMaxPointsPerBlock", + "Group size over 2 with multiple files under 2GB and at DefaultAggressiveMaxPointsPerBlock", []tsm1.FileStat{ { Path: "01-13.tsm1", @@ -2729,9 +2729,9 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { Size: 450 * 1024 * 1024, }, }, []int{ - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, - tsdb.AggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, }, "", 0, }, } diff --git a/tsdb/engine/tsm1/engine.go b/tsdb/engine/tsm1/engine.go index cb07db1a595..c5598c2cbc2 100644 --- a/tsdb/engine/tsm1/engine.go +++ b/tsdb/engine/tsm1/engine.go @@ -2167,14 +2167,14 @@ func (e *Engine) compact(wg *sync.WaitGroup) { level3Groups = level3Groups[1:] } case 4: - // This is a heuristic. 100_000 points per block is suitable for when we have a + // This is a heuristic. The 10_000 points per block default is suitable for when we have a // single generation with multiple files at max block size under 2 GB. if genLen == 1 { // Log TSM files that will have an increased points per block count. for _, f := range level4Groups[0] { - e.logger.Info("TSM optimized compaction on single generation running, increasing total points per block to 100_000.", zap.String("path", f)) + e.logger.Info("TSM optimized compaction on single generation running, increasing total points per block.", zap.String("path", f), zap.Int("points-per-block", tsdb.DefaultAggressiveMaxPointsPerBlock)) } - e.Compactor.Size = tsdb.AggressiveMaxPointsPerBlock + e.Compactor.Size = tsdb.DefaultAggressiveMaxPointsPerBlock } else { e.Compactor.Size = tsdb.DefaultMaxPointsPerBlock } From ea0bdbf650905bd41952190b1b96d5d2c298204a Mon Sep 17 00:00:00 2001 From: devanbenz Date: Tue, 4 Mar 2025 12:14:32 -0600 Subject: [PATCH 2/9] feat: update example config file --- etc/config.sample.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/config.sample.toml b/etc/config.sample.toml index e66d9290c3d..b885bf7e676 100644 --- a/etc/config.sample.toml +++ b/etc/config.sample.toml @@ -124,6 +124,11 @@ # will allow TSM compactions to write to disk. # compact-throughput-burst = "48m" + # CompactPointsPerBlock is the points per block to be used when aggressive + # compaction is used. There are certain cases where TSM files do not get + # fully compacted. This adjusts an internal parameter that alleviates that. + # compact-points-per-block = 10000 + # If true, then the mmap advise value MADV_WILLNEED will be provided to the kernel with respect to # TSM files. This setting has been found to be problematic on some kernels, and defaults to off. # It might help users who have slow disks in some cases. From 0c81d8df74c13abfdfa20314297badad31a54c63 Mon Sep 17 00:00:00 2001 From: Devan Date: Tue, 4 Mar 2025 16:08:49 -0600 Subject: [PATCH 3/9] feat: Create a way to use the config value for compaction points per block Add additional testing to verify that override value works for SetAggressiveCompactionPointsPerBlock --- tsdb/engine/tsm1/compact.go | 19 ++++- tsdb/engine/tsm1/compact_test.go | 140 +++++++++++++++++++++++++++++++ tsdb/engine/tsm1/engine.go | 1 + tsdb/engine/tsm1/engine_test.go | 3 + 4 files changed, 159 insertions(+), 4 deletions(-) diff --git a/tsdb/engine/tsm1/compact.go b/tsdb/engine/tsm1/compact.go index 5512786fd15..32a7e275588 100644 --- a/tsdb/engine/tsm1/compact.go +++ b/tsdb/engine/tsm1/compact.go @@ -124,6 +124,8 @@ type CompactionPlanner interface { ForceFull() SetFileStore(fs *FileStore) + + SetAggressiveCompactionPointsPerBlock(aggressiveCompactionPointsPerBlock int) } // DefaultPlanner implements CompactionPlanner using a strategy to roll up @@ -157,6 +159,10 @@ type DefaultPlanner struct { // filesInUse is the set of files that have been returned as part of a plan and might // be being compacted. Two plans should not return the same file at any given time. filesInUse map[string]struct{} + + // aggressiveCompactionPointsPerBlock is the amount of points that should be + // packed in to a TSM file block during aggressive compaction + aggressiveCompactionPointsPerBlock int } type fileStore interface { @@ -168,9 +174,10 @@ type fileStore interface { func NewDefaultPlanner(fs fileStore, writeColdDuration time.Duration) *DefaultPlanner { return &DefaultPlanner{ - FileStore: fs, - compactFullWriteColdDuration: writeColdDuration, - filesInUse: make(map[string]struct{}), + FileStore: fs, + compactFullWriteColdDuration: writeColdDuration, + filesInUse: make(map[string]struct{}), + aggressiveCompactionPointsPerBlock: tsdb.DefaultAggressiveMaxPointsPerBlock, } } @@ -228,6 +235,10 @@ func (t *tsmGeneration) hasTombstones() bool { return false } +func (c *DefaultPlanner) SetAggressiveCompactionPointsPerBlock(aggressiveCompactionPointsPerBlock int) { + c.aggressiveCompactionPointsPerBlock = aggressiveCompactionPointsPerBlock +} + func (c *DefaultPlanner) SetFileStore(fs *FileStore) { c.FileStore = fs } @@ -253,7 +264,7 @@ func (c *DefaultPlanner) FullyCompacted() (bool, string) { aggressivePointsPerBlockCount := 0 filesUnderMaxTsmSizeCount := 0 for _, tsmFile := range gens[0].files { - if c.FileStore.BlockCount(tsmFile.Path, 1) >= tsdb.DefaultAggressiveMaxPointsPerBlock { + if c.FileStore.BlockCount(tsmFile.Path, 1) >= c.aggressiveCompactionPointsPerBlock { aggressivePointsPerBlockCount++ } if tsmFile.Size < tsdb.MaxTSMFileSize { diff --git a/tsdb/engine/tsm1/compact_test.go b/tsdb/engine/tsm1/compact_test.go index 04dcf3828f7..d153dbbbc8f 100644 --- a/tsdb/engine/tsm1/compact_test.go +++ b/tsdb/engine/tsm1/compact_test.go @@ -2786,6 +2786,146 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { expectedFullyCompacted(cp, test.expectedFullyCompactedReasonExp) }) } + + type PlanOptimizeMixedTests struct { + name string + fs []tsm1.FileStat + bc []int + expectedFullyCompactedReasonExp string + expectedgenerationCount int64 + fullyCompacted bool + } + + setUpperAreNotFullyCompacted := []PlanOptimizeMixedTests{ + { + // This test is added to account for halting state after + // TestDefaultPlanner_FullyCompacted_SmallSingleGeneration + // will need to ensure that once we have single TSM file under 2 GB we stop + "Single TSM file with increase block count", + []tsm1.FileStat{ + { + Path: "01-09.tsm1", + Size: 650 * 1024 * 1024, + }, + }, + []int{}, + "", 0, true, + }, + { + // This test is added to account for a single generation that has a group size + // over 2 GB with 1 file under 2 GB all at max points per block with aggressive compaction. + // It should not compact any further. + "TSM files at DefaultAggressiveMaxPointsPerBlock with increased block count", + []tsm1.FileStat{ + { + Path: "01-13.tsm1", + Size: 2048 * 1024 * 1024, + }, + { + Path: "01-14.tsm1", + Size: 691 * 1024 * 1024, + }, + }, []int{ + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + }, "", 0, true, + }, + { + // This test is added to account for a single generation that has a group size + // over 2 GB at max points per block with aggressive compaction, and, 1 file + // under 2 GB at default max points per block. + // It should not compact any further. + "TSM files cannot compact further, single file under 2G and at DefaultMaxPointsPerBlock with increased block count", + []tsm1.FileStat{ + { + Path: "01-13.tsm1", + Size: 2048 * 1024 * 1024, + }, + { + Path: "01-14.tsm1", + Size: 691 * 1024 * 1024, + }, + }, []int{ + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultMaxPointsPerBlock, + }, + "", + 0, true, + }, + { + // This test is added to account for a single generation that has a group size + // over 2 GB and multiple files under 2 GB all at max points per block for aggressive compaction. + "Group size over 2 with multiple files under 2GB and at DefaultAggressiveMaxPointsPerBlock with increased block count", + []tsm1.FileStat{ + { + Path: "01-13.tsm1", + Size: 2048 * 1024 * 1024, + }, + { + Path: "01-14.tsm1", + Size: 650 * 1024 * 1024, + }, + { + Path: "01-15.tsm1", + Size: 450 * 1024 * 1024, + }, + }, []int{ + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + tsdb.DefaultAggressiveMaxPointsPerBlock, + }, tsdb.SingleGenerationReasonText, 1, false, + }, + } + + maxBlocksNotFullyCompacted := func(cp *tsm1.DefaultPlanner, reasonExp string, fullyCompacted bool) { + compacted, reason := cp.FullyCompacted() + require.Equal(t, reason, reasonExp, "fullyCompacted reason") + require.Equal(t, compacted, fullyCompacted, "is fully compacted") + + // Ensure that no level planning takes place + _, cgLen := cp.PlanLevel(1) + require.Zero(t, cgLen, "compaction group length; PlanLevel(1)") + _, cgLen = cp.PlanLevel(2) + require.Zero(t, cgLen, "compaction group length; PlanLevel(2)") + _, cgLen = cp.PlanLevel(3) + require.Zero(t, cgLen, "compaction group length; PlanLevel(3)") + } + + // These tests will decrease the max points per block for aggressive compaction. + for _, test := range setUpperAreNotFullyCompacted { + t.Run(test.name, func(t *testing.T) { + ffs := &fakeFileStore{ + PathsFn: func() []tsm1.FileStat { + return test.fs + }, + } + + if len(test.bc) > 0 { + err := ffs.SetBlockCounts(test.bc) + require.NoError(t, err, "setting block counts") + } + + cp := tsm1.NewDefaultPlanner(ffs, tsdb.DefaultCompactFullWriteColdDuration) + cp.SetAggressiveCompactionPointsPerBlock(tsdb.DefaultAggressiveMaxPointsPerBlock * 10) + maxBlocksNotFullyCompacted(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) + + // Reverse test files and re-run tests + slices.Reverse(test.fs) + if len(test.bc) > 0 { + slices.Reverse(test.bc) + err := ffs.SetBlockCounts(test.bc) + require.NoError(t, err, "setting reverse block counts") + } + + cp = tsm1.NewDefaultPlanner(ffs, tsdb.DefaultCompactFullWriteColdDuration) + cp.SetAggressiveCompactionPointsPerBlock(tsdb.DefaultAggressiveMaxPointsPerBlock * 10) + maxBlocksNotFullyCompacted(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) + }) + } +} + +func TestDefaultPlanner_PointsPerBlockParameter(t *testing.T) { + } func TestDefaultPlanner_PlanOptimize_Tombstones(t *testing.T) { diff --git a/tsdb/engine/tsm1/engine.go b/tsdb/engine/tsm1/engine.go index c5598c2cbc2..923b1c2b2c4 100644 --- a/tsdb/engine/tsm1/engine.go +++ b/tsdb/engine/tsm1/engine.go @@ -233,6 +233,7 @@ func NewEngine(id uint64, idx tsdb.Index, path string, walPath string, sfile *ts if opt.CompactionPlannerCreator != nil { planner = opt.CompactionPlannerCreator(opt.Config).(CompactionPlanner) planner.SetFileStore(fs) + planner.SetAggressiveCompactionPointsPerBlock(int(opt.Config.CompactPointsPerBlock)) } logger := zap.NewNop() diff --git a/tsdb/engine/tsm1/engine_test.go b/tsdb/engine/tsm1/engine_test.go index 41b030ebfe3..4d0efacdbaa 100644 --- a/tsdb/engine/tsm1/engine_test.go +++ b/tsdb/engine/tsm1/engine_test.go @@ -2887,6 +2887,9 @@ func MustParsePointString(buf string) models.Point { return MustParsePointsStrin type mockPlanner struct{} +func (m *mockPlanner) SetAggressiveCompactionPointsPerBlock(aggressiveCompactionPointsPerBlock int) { + return +} func (m *mockPlanner) Plan(lastWrite time.Time) ([]tsm1.CompactionGroup, int64) { return nil, 0 } func (m *mockPlanner) PlanLevel(level int) ([]tsm1.CompactionGroup, int64) { return nil, 0 } func (m *mockPlanner) PlanOptimize() ([]tsm1.CompactionGroup, int64, int64) { return nil, 0, 0 } From ff4c531c0b056187f1418d025c4e6e1b7ddba02f Mon Sep 17 00:00:00 2001 From: Devan Date: Tue, 4 Mar 2025 16:14:17 -0600 Subject: [PATCH 4/9] feat: Modify Engine.compact to set the AggressivePointsPerBlock correctly --- tsdb/engine/tsm1/compact.go | 6 ++++++ tsdb/engine/tsm1/engine.go | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tsdb/engine/tsm1/compact.go b/tsdb/engine/tsm1/compact.go index 32a7e275588..98cd52863ff 100644 --- a/tsdb/engine/tsm1/compact.go +++ b/tsdb/engine/tsm1/compact.go @@ -126,6 +126,8 @@ type CompactionPlanner interface { SetFileStore(fs *FileStore) SetAggressiveCompactionPointsPerBlock(aggressiveCompactionPointsPerBlock int) + + GetAggressiveCompactionPointsPerBlock() int } // DefaultPlanner implements CompactionPlanner using a strategy to roll up @@ -239,6 +241,10 @@ func (c *DefaultPlanner) SetAggressiveCompactionPointsPerBlock(aggressiveCompact c.aggressiveCompactionPointsPerBlock = aggressiveCompactionPointsPerBlock } +func (c *DefaultPlanner) GetAggressiveCompactionPointsPerBlock() int { + return c.aggressiveCompactionPointsPerBlock +} + func (c *DefaultPlanner) SetFileStore(fs *FileStore) { c.FileStore = fs } diff --git a/tsdb/engine/tsm1/engine.go b/tsdb/engine/tsm1/engine.go index 923b1c2b2c4..fd0ba51e5c2 100644 --- a/tsdb/engine/tsm1/engine.go +++ b/tsdb/engine/tsm1/engine.go @@ -2173,9 +2173,9 @@ func (e *Engine) compact(wg *sync.WaitGroup) { if genLen == 1 { // Log TSM files that will have an increased points per block count. for _, f := range level4Groups[0] { - e.logger.Info("TSM optimized compaction on single generation running, increasing total points per block.", zap.String("path", f), zap.Int("points-per-block", tsdb.DefaultAggressiveMaxPointsPerBlock)) + e.logger.Info("TSM optimized compaction on single generation running, increasing total points per block.", zap.String("path", f), zap.Int("points-per-block", e.CompactionPlan.GetAggressiveCompactionPointsPerBlock())) } - e.Compactor.Size = tsdb.DefaultAggressiveMaxPointsPerBlock + e.Compactor.Size = e.CompactionPlan.GetAggressiveCompactionPointsPerBlock() } else { e.Compactor.Size = tsdb.DefaultMaxPointsPerBlock } From 29bde57e7199cddc2f8456b327ecfab30d58ba2f Mon Sep 17 00:00:00 2001 From: Devan Date: Tue, 4 Mar 2025 16:15:46 -0600 Subject: [PATCH 5/9] chore: add mock interface --- tsdb/engine/tsm1/engine_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tsdb/engine/tsm1/engine_test.go b/tsdb/engine/tsm1/engine_test.go index 4d0efacdbaa..19b36eb91f3 100644 --- a/tsdb/engine/tsm1/engine_test.go +++ b/tsdb/engine/tsm1/engine_test.go @@ -2887,6 +2887,7 @@ func MustParsePointString(buf string) models.Point { return MustParsePointsStrin type mockPlanner struct{} +func (m *mockPlanner) GetAggressiveCompactionPointsPerBlock() int { return 0 } func (m *mockPlanner) SetAggressiveCompactionPointsPerBlock(aggressiveCompactionPointsPerBlock int) { return } From ecb359d1a446a7dbe805709ebe8b54ba46be88c6 Mon Sep 17 00:00:00 2001 From: Devan Date: Tue, 4 Mar 2025 16:18:03 -0600 Subject: [PATCH 6/9] feat: Modify the name of config item --- etc/config.sample.toml | 4 ++-- tsdb/config.go | 4 ++-- tsdb/engine/tsm1/engine.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/etc/config.sample.toml b/etc/config.sample.toml index b885bf7e676..7a76d30683b 100644 --- a/etc/config.sample.toml +++ b/etc/config.sample.toml @@ -124,10 +124,10 @@ # will allow TSM compactions to write to disk. # compact-throughput-burst = "48m" - # CompactPointsPerBlock is the points per block to be used when aggressive + # AggressivePointsPerBlock is the points per block to be used when aggressive # compaction is used. There are certain cases where TSM files do not get # fully compacted. This adjusts an internal parameter that alleviates that. - # compact-points-per-block = 10000 + # aggressive-points-per-block = 10000 # If true, then the mmap advise value MADV_WILLNEED will be provided to the kernel with respect to # TSM files. This setting has been found to be problematic on some kernels, and defaults to off. diff --git a/tsdb/config.go b/tsdb/config.go index 675194e80a2..89becf97f19 100644 --- a/tsdb/config.go +++ b/tsdb/config.go @@ -128,7 +128,7 @@ type Config struct { CompactFullWriteColdDuration toml.Duration `toml:"compact-full-write-cold-duration"` CompactThroughput toml.Size `toml:"compact-throughput"` CompactThroughputBurst toml.Size `toml:"compact-throughput-burst"` - CompactPointsPerBlock toml.Size `toml:"compact-points-per-block"` + AggressivePointsPerBlock toml.Size `toml:"aggressive-points-per-block"` // Options for ingress metrics IngressMetricByMeasurement bool `toml:"ingress-metric-by-measurement-enabled"` @@ -198,7 +198,7 @@ func NewConfig() Config { CompactFullWriteColdDuration: toml.Duration(DefaultCompactFullWriteColdDuration), CompactThroughput: toml.Size(DefaultCompactThroughput), CompactThroughputBurst: toml.Size(DefaultCompactThroughputBurst), - CompactPointsPerBlock: toml.Size(DefaultAggressiveMaxPointsPerBlock), + AggressivePointsPerBlock: toml.Size(DefaultAggressiveMaxPointsPerBlock), MaxSeriesPerDatabase: DefaultMaxSeriesPerDatabase, MaxValuesPerTag: DefaultMaxValuesPerTag, diff --git a/tsdb/engine/tsm1/engine.go b/tsdb/engine/tsm1/engine.go index fd0ba51e5c2..1c93adea4ce 100644 --- a/tsdb/engine/tsm1/engine.go +++ b/tsdb/engine/tsm1/engine.go @@ -233,7 +233,7 @@ func NewEngine(id uint64, idx tsdb.Index, path string, walPath string, sfile *ts if opt.CompactionPlannerCreator != nil { planner = opt.CompactionPlannerCreator(opt.Config).(CompactionPlanner) planner.SetFileStore(fs) - planner.SetAggressiveCompactionPointsPerBlock(int(opt.Config.CompactPointsPerBlock)) + planner.SetAggressiveCompactionPointsPerBlock(int(opt.Config.AggressivePointsPerBlock)) } logger := zap.NewNop() From 0de2ad1b8075779271fcfc25b322518d50567dbb Mon Sep 17 00:00:00 2001 From: Devan Date: Tue, 4 Mar 2025 16:24:42 -0600 Subject: [PATCH 7/9] feat: Adjust where planner calls SetAggressivePointsPerBlock --- tsdb/engine/tsm1/engine.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsdb/engine/tsm1/engine.go b/tsdb/engine/tsm1/engine.go index 1c93adea4ce..9518d4801f0 100644 --- a/tsdb/engine/tsm1/engine.go +++ b/tsdb/engine/tsm1/engine.go @@ -230,10 +230,11 @@ func NewEngine(id uint64, idx tsdb.Index, path string, walPath string, sfile *ts c.RateLimit = opt.CompactionThroughputLimiter var planner CompactionPlanner = NewDefaultPlanner(fs, time.Duration(opt.Config.CompactFullWriteColdDuration)) + planner.SetAggressiveCompactionPointsPerBlock(int(opt.Config.AggressivePointsPerBlock)) + if opt.CompactionPlannerCreator != nil { planner = opt.CompactionPlannerCreator(opt.Config).(CompactionPlanner) planner.SetFileStore(fs) - planner.SetAggressiveCompactionPointsPerBlock(int(opt.Config.AggressivePointsPerBlock)) } logger := zap.NewNop() From 722a7e33de6676210a14c52382b90154bd4071f5 Mon Sep 17 00:00:00 2001 From: Devan Date: Wed, 5 Mar 2025 10:21:17 -0600 Subject: [PATCH 8/9] feat: modify test comment, adjust typo in comment, modify sprintf for b/p --- tsdb/config.go | 4 ++-- tsdb/engine/tsm1/compact_test.go | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tsdb/config.go b/tsdb/config.go index 89becf97f19..ae2ed8dcbef 100644 --- a/tsdb/config.go +++ b/tsdb/config.go @@ -53,7 +53,7 @@ const ( DefaultMaxPointsPerBlock = 1000 // DefaultAggressiveMaxPointsPerBlock is used when we want to further compact blocks - // it is 100 times the default amount of points we use per block + // it is 10 times the default amount of points we use per block DefaultAggressiveMaxPointsPerBlock = DefaultMaxPointsPerBlock * 10 // DefaultMaxSeriesPerDatabase is the maximum number of series a node can hold per database. @@ -92,7 +92,7 @@ var SingleGenerationReasonText string = SingleGenerationReason() // when checked for full compaction. // 1048576000 is a magic number for bytes per gigabyte. func SingleGenerationReason() string { - return fmt.Sprintf("not fully compacted and not idle because single generation with more than 2 files under %d GB and more than 1 file(s) under aggressive compaction points per block count (%d points)", int(MaxTSMFileSize/1048576000), DefaultAggressiveMaxPointsPerBlock) + return fmt.Sprintf("not fully compacted and not idle because single generation with more than 2 files under %d GB and more than 1 file(s) under aggressive compaction points per block count (default: %d points)", int(MaxTSMFileSize/1048576000), DefaultAggressiveMaxPointsPerBlock) } // Config holds the configuration for the tsbd package. diff --git a/tsdb/engine/tsm1/compact_test.go b/tsdb/engine/tsm1/compact_test.go index d153dbbbc8f..1b12f6c749e 100644 --- a/tsdb/engine/tsm1/compact_test.go +++ b/tsdb/engine/tsm1/compact_test.go @@ -2892,6 +2892,9 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { } // These tests will decrease the max points per block for aggressive compaction. + // For SetAggressiveCompactionPointsPerBlock we are using 10x the default to + // mock an administrator setting the max points per block to 100_000 and overriding + // the default of 10_000. for _, test := range setUpperAreNotFullyCompacted { t.Run(test.name, func(t *testing.T) { ffs := &fakeFileStore{ @@ -2924,10 +2927,6 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { } } -func TestDefaultPlanner_PointsPerBlockParameter(t *testing.T) { - -} - func TestDefaultPlanner_PlanOptimize_Tombstones(t *testing.T) { data := []tsm1.FileStat{ { From 4fd3df6be42377982600786404254247d7ef3ff1 Mon Sep 17 00:00:00 2001 From: devanbenz Date: Wed, 5 Mar 2025 14:36:46 -0600 Subject: [PATCH 9/9] chore: rename some test variables --- tsdb/engine/tsm1/compact_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tsdb/engine/tsm1/compact_test.go b/tsdb/engine/tsm1/compact_test.go index 1b12f6c749e..f14ae82ebb5 100644 --- a/tsdb/engine/tsm1/compact_test.go +++ b/tsdb/engine/tsm1/compact_test.go @@ -2796,7 +2796,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { fullyCompacted bool } - setUpperAreNotFullyCompacted := []PlanOptimizeMixedTests{ + mixedPlanOptimizeTests := []PlanOptimizeMixedTests{ { // This test is added to account for halting state after // TestDefaultPlanner_FullyCompacted_SmallSingleGeneration @@ -2877,7 +2877,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { }, } - maxBlocksNotFullyCompacted := func(cp *tsm1.DefaultPlanner, reasonExp string, fullyCompacted bool) { + mixedPlanOptimizeTestRunner := func(cp *tsm1.DefaultPlanner, reasonExp string, fullyCompacted bool) { compacted, reason := cp.FullyCompacted() require.Equal(t, reason, reasonExp, "fullyCompacted reason") require.Equal(t, compacted, fullyCompacted, "is fully compacted") @@ -2895,7 +2895,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { // For SetAggressiveCompactionPointsPerBlock we are using 10x the default to // mock an administrator setting the max points per block to 100_000 and overriding // the default of 10_000. - for _, test := range setUpperAreNotFullyCompacted { + for _, test := range mixedPlanOptimizeTests { t.Run(test.name, func(t *testing.T) { ffs := &fakeFileStore{ PathsFn: func() []tsm1.FileStat { @@ -2910,7 +2910,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { cp := tsm1.NewDefaultPlanner(ffs, tsdb.DefaultCompactFullWriteColdDuration) cp.SetAggressiveCompactionPointsPerBlock(tsdb.DefaultAggressiveMaxPointsPerBlock * 10) - maxBlocksNotFullyCompacted(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) + mixedPlanOptimizeTestRunner(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) // Reverse test files and re-run tests slices.Reverse(test.fs) @@ -2922,7 +2922,7 @@ func TestDefaultPlanner_PlanOptimize_Test(t *testing.T) { cp = tsm1.NewDefaultPlanner(ffs, tsdb.DefaultCompactFullWriteColdDuration) cp.SetAggressiveCompactionPointsPerBlock(tsdb.DefaultAggressiveMaxPointsPerBlock * 10) - maxBlocksNotFullyCompacted(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) + mixedPlanOptimizeTestRunner(cp, test.expectedFullyCompactedReasonExp, test.fullyCompacted) }) } }