Skip to content

Commit ab701c7

Browse files
fix(meta): limit file count and l0 compact score (risingwavelabs#8563)
Signed-off-by: Little-Wallace <[email protected]>
1 parent 4f430ac commit ab701c7

File tree

7 files changed

+45
-14
lines changed

7 files changed

+45
-14
lines changed

dashboard/proto/gen/hummock.ts

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proto/hummock.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ message CompactionConfig {
605605
bool split_by_state_table = 14;
606606
// soft limit for max number of sub level number
607607
uint64 level0_stop_write_threshold_sub_level_number = 15;
608+
uint64 level0_max_compact_file_number = 16;
608609
}
609610

610611
message TableStats {

src/meta/src/hummock/compaction/compaction_config.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use risingwave_pb::hummock::compaction_config::CompactionMode;
1717
use risingwave_pb::hummock::CompactionConfig;
1818

1919
const DEFAULT_MAX_COMPACTION_BYTES: u64 = 2 * 1024 * 1024 * 1024; // 2GB
20-
const DEFAULT_MIN_COMPACTION_BYTES: u64 = 256 * 1024 * 1024; // 256MB
20+
const DEFAULT_MIN_COMPACTION_BYTES: u64 = 128 * 1024 * 1024; // 128MB
2121
const DEFAULT_MAX_BYTES_FOR_LEVEL_BASE: u64 = 512 * 1024 * 1024; // 512MB
2222

2323
// decrease this configure when the generation of checkpoint barrier is not frequent.
@@ -28,6 +28,7 @@ const MAX_LEVEL: u64 = 6;
2828
const DEFAULT_LEVEL_MULTIPLIER: u64 = 5;
2929
const DEFAULT_MAX_SPACE_RECLAIM_BYTES: u64 = 512 * 1024 * 1024; // 512MB;
3030
const DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_SUB_LEVEL_NUMBER: u64 = u32::MAX as u64;
31+
const DEFAULT_MAX_COMPACTION_FILE_COUNT: u64 = 96;
3132

3233
pub struct CompactionConfigBuilder {
3334
config: CompactionConfig,
@@ -65,6 +66,11 @@ impl CompactionConfigBuilder {
6566
split_by_state_table: false,
6667
level0_stop_write_threshold_sub_level_number:
6768
DEFAULT_LEVEL0_STOP_WRITE_THRESHOLD_SUB_LEVEL_NUMBER,
69+
// This configure variable shall be larger than level0_tier_compact_file_number, and
70+
// it shall meet the following condition:
71+
// level0_max_compact_file_number * target_file_size_base >
72+
// max_bytes_for_level_base
73+
level0_max_compact_file_number: DEFAULT_MAX_COMPACTION_FILE_COUNT,
6874
},
6975
}
7076
}
@@ -127,4 +133,5 @@ builder_field! {
127133
max_sub_compaction: u32,
128134
max_space_reclaim_bytes: u64,
129135
level0_stop_write_threshold_sub_level_number: u64,
136+
level0_max_compact_file_number: u64,
130137
}

src/meta/src/hummock/compaction/level_selector.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::collections::HashMap;
2020
use std::sync::Arc;
2121

2222
use risingwave_common::catalog::TableOption;
23+
use risingwave_hummock_sdk::compaction_group::hummock_version_ext::HummockLevelsExt;
2324
use risingwave_hummock_sdk::HummockCompactionTaskId;
2425
use risingwave_pb::hummock::hummock_version::Levels;
2526
use risingwave_pb::hummock::{compact_task, CompactionConfig};
@@ -200,13 +201,15 @@ impl DynamicLevelSelectorCore {
200201

201202
let total_size = levels.l0.as_ref().unwrap().total_file_size
202203
- handlers[0].get_pending_output_file_size(ctx.base_level as u32);
204+
let base_level_size = levels.get_level(ctx.base_level).total_file_size;
203205
if idle_file_count > 0 {
204206
// trigger intra-l0 compaction at first when the number of files is too large.
205207
let l0_score =
206208
idle_file_count as u64 * SCORE_BASE / self.config.level0_tier_compact_file_number;
207209
ctx.score_levels
208210
.push((std::cmp::min(l0_score, max_l0_score), 0, 0));
209-
let score = total_size * SCORE_BASE / self.config.max_bytes_for_level_base;
211+
let score = total_size * SCORE_BASE
212+
/ std::cmp::max(self.config.max_bytes_for_level_base, base_level_size);
210213
ctx.score_levels.push((score, 0, ctx.base_level));
211214
}
212215

src/meta/src/hummock/compaction/picker/base_level_compaction_picker.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ impl LevelCompactionPicker {
109109
) -> Option<CompactionInput> {
110110
let mut input_levels = vec![];
111111
let mut l0_total_file_size = 0;
112+
let mut l0_total_file_count = 0;
112113
for level in &l0.sub_levels {
113114
// This break is optional. We can include overlapping sub-level actually.
114115
if level.level_type() != LevelType::Nonoverlapping {
@@ -118,6 +119,10 @@ impl LevelCompactionPicker {
118119
break;
119120
}
120121

122+
if l0_total_file_count > self.config.level0_max_compact_file_number {
123+
break;
124+
}
125+
121126
let mut pending_compact = false;
122127
let mut cur_level_size = 0;
123128
let mut select_level = InputLevel {
@@ -144,6 +149,7 @@ impl LevelCompactionPicker {
144149
continue;
145150
}
146151

152+
l0_total_file_count += select_level.table_infos.len() as u64;
147153
l0_total_file_size += cur_level_size;
148154
input_levels.push(select_level);
149155
}
@@ -163,9 +169,7 @@ impl LevelCompactionPicker {
163169
target_level_size += sst.file_size;
164170
}
165171

166-
if target_level_size > l0_total_file_size
167-
&& l0_total_file_size < self.config.max_compaction_bytes
168-
{
172+
if target_level_size > l0_total_file_size {
169173
stats.skip_by_write_amp_limit += 1;
170174
return None;
171175
}
@@ -440,7 +444,7 @@ pub mod tests {
440444
.is_none());
441445
}
442446

443-
// compact the whole level and upper sub-level when the write-amplification is more than 1.5.
447+
// compact the whole level and upper sub-level when the write-amplification is more than 1.0.
444448
#[test]
445449
fn test_compact_whole_level_write_amplification_limit() {
446450
let config = CompactionConfigBuilder::new()
@@ -497,10 +501,8 @@ pub mod tests {
497501
sub_level.table_infos[0].file_size += 1000 - sub_level.total_file_size;
498502
sub_level.total_file_size = 1000;
499503
levels.l0.as_mut().unwrap().sub_levels[1].total_file_size = 1000;
500-
let ret = picker
501-
.pick_compaction(&levels, &levels_handler, &mut local_stats)
502-
.unwrap();
503-
assert_eq!(ret.input_levels.len(), 2);
504+
let ret = picker.pick_compaction(&levels, &levels_handler, &mut local_stats);
505+
assert!(ret.is_none());
504506
}
505507

506508
#[test]

src/meta/src/hummock/compaction/picker/tier_compaction_picker.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,15 @@ impl TierCompactionPicker {
6969
);
7070
let mut compaction_bytes = level.total_file_size;
7171
let mut max_level_size = level.total_file_size;
72+
let mut compact_file_count = level.table_infos.len() as u64;
7273

7374
for other in &l0.sub_levels[idx + 1..] {
7475
if compaction_bytes > max_compaction_bytes {
7576
break;
7677
}
77-
78+
if compact_file_count > self.config.level0_max_compact_file_number {
79+
break;
80+
}
7881
if other.level_type != non_overlapping_type
7982
|| other.total_file_size > self.config.sub_level_max_compaction_bytes
8083
{
@@ -85,6 +88,7 @@ impl TierCompactionPicker {
8588
}
8689

8790
compaction_bytes += other.total_file_size;
91+
compact_file_count += other.table_infos.len() as u64;
8892
max_level_size = std::cmp::max(max_level_size, other.total_file_size);
8993
select_level_inputs.push(InputLevel {
9094
level_idx: 0,
@@ -107,6 +111,7 @@ impl TierCompactionPicker {
107111
if level.level_type == non_overlapping_type
108112
&& is_write_amp_large
109113
&& select_level_inputs.len() < self.config.level0_tier_compact_file_number as usize
114+
&& compact_file_count < self.config.level0_max_compact_file_number
110115
{
111116
stats.skip_by_write_amp_limit += 1;
112117
continue;
@@ -303,7 +308,7 @@ impl TierCompactionPicker {
303308
);
304309

305310
let mut compaction_bytes = level.total_file_size;
306-
let mut compact_file_count = level.table_infos.len();
311+
let mut compact_file_count = level.table_infos.len() as u64;
307312
let mut waiting_enough_files = true;
308313

309314
for other in &l0.sub_levels[idx + 1..] {
@@ -312,6 +317,10 @@ impl TierCompactionPicker {
312317
break;
313318
}
314319

320+
if compact_file_count > self.config.level0_max_compact_file_number {
321+
break;
322+
}
323+
315324
if other.level_type != overlapping_type {
316325
waiting_enough_files = false;
317326
break;
@@ -322,15 +331,15 @@ impl TierCompactionPicker {
322331
}
323332

324333
compaction_bytes += other.total_file_size;
325-
compact_file_count += other.table_infos.len();
334+
compact_file_count += other.table_infos.len() as u64;
326335
select_level_inputs.push(InputLevel {
327336
level_idx: 0,
328337
level_type: other.level_type,
329338
table_infos: other.table_infos.clone(),
330339
});
331340
}
332341

333-
if compact_file_count < self.config.level0_tier_compact_file_number as usize
342+
if compact_file_count < self.config.level0_tier_compact_file_number
334343
&& waiting_enough_files
335344
{
336345
stats.skip_by_count_limit += 1;

src/meta/src/hummock/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ pub async fn setup_compute_env(
338338
) {
339339
let config = CompactionConfigBuilder::new()
340340
.level0_tier_compact_file_number(1)
341+
.level0_max_compact_file_number(130)
341342
.build();
342343
setup_compute_env_with_config(port, config).await
343344
}

0 commit comments

Comments
 (0)