add simple leveled compaction
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
This commit is contained in:
100
mini-lsm/src/compact/simple_leveled.rs
Normal file
100
mini-lsm/src/compact/simple_leveled.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::lsm_storage::LsmStorageInner;
|
||||
|
||||
pub struct SimpleLeveledCompactionOptions {
|
||||
pub size_ratio_percent: usize,
|
||||
pub level0_file_num_compaction_trigger: usize,
|
||||
pub max_levels: usize,
|
||||
}
|
||||
|
||||
pub struct SimpleLeveledCompactionTask {
|
||||
// if upper_level is `None`, then it is L0 compaction
|
||||
pub upper_level: Option<usize>,
|
||||
pub upper_level_sst_ids: Vec<usize>,
|
||||
pub lower_level: usize,
|
||||
pub lower_level_sst_ids: Vec<usize>,
|
||||
}
|
||||
|
||||
pub struct SimpleLeveledCompactionController {
|
||||
options: SimpleLeveledCompactionOptions,
|
||||
}
|
||||
|
||||
impl SimpleLeveledCompactionController {
|
||||
pub fn new(options: SimpleLeveledCompactionOptions) -> Self {
|
||||
Self { options }
|
||||
}
|
||||
|
||||
pub fn generate_compaction_task(
|
||||
&mut self,
|
||||
snapshot: &LsmStorageInner,
|
||||
) -> Option<SimpleLeveledCompactionTask> {
|
||||
let mut level_sizes = Vec::new();
|
||||
level_sizes.push(snapshot.l0_sstables.len());
|
||||
for (_, files) in &snapshot.levels {
|
||||
level_sizes.push(files.len());
|
||||
}
|
||||
|
||||
for i in 0..self.options.max_levels {
|
||||
if i == 0
|
||||
&& snapshot.l0_sstables.len() < self.options.level0_file_num_compaction_trigger
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let lower_level = i + 1;
|
||||
let size_ratio = level_sizes[lower_level] as f64 / level_sizes[i] as f64;
|
||||
if size_ratio < self.options.size_ratio_percent as f64 / 100.0 {
|
||||
println!(
|
||||
"compaction triggered at level {} and {} with size ratio {}",
|
||||
i, lower_level, size_ratio
|
||||
);
|
||||
return Some(SimpleLeveledCompactionTask {
|
||||
upper_level: if i == 0 { None } else { Some(i) },
|
||||
upper_level_sst_ids: if i == 0 {
|
||||
snapshot.l0_sstables.clone()
|
||||
} else {
|
||||
snapshot.levels[i - 1].1.clone()
|
||||
},
|
||||
lower_level,
|
||||
lower_level_sst_ids: snapshot.levels[lower_level - 1].1.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn apply_compaction_result(
|
||||
&self,
|
||||
snapshot: &LsmStorageInner,
|
||||
task: &SimpleLeveledCompactionTask,
|
||||
output: &[usize],
|
||||
) -> (LsmStorageInner, Vec<usize>) {
|
||||
let mut snapshot = snapshot.clone();
|
||||
let mut files_to_remove = Vec::new();
|
||||
if let Some(upper_level) = task.upper_level {
|
||||
assert_eq!(
|
||||
task.upper_level_sst_ids,
|
||||
snapshot.levels[upper_level - 1].1,
|
||||
"sst mismatched"
|
||||
);
|
||||
files_to_remove.extend(&snapshot.levels[upper_level - 1].1);
|
||||
snapshot.levels[upper_level - 1].1.clear();
|
||||
} else {
|
||||
assert_eq!(
|
||||
task.upper_level_sst_ids, snapshot.l0_sstables,
|
||||
"sst mismatched"
|
||||
);
|
||||
files_to_remove.extend(&snapshot.l0_sstables);
|
||||
snapshot.l0_sstables.clear();
|
||||
}
|
||||
assert_eq!(
|
||||
task.lower_level_sst_ids,
|
||||
snapshot.levels[task.lower_level - 1].1,
|
||||
"sst mismatched"
|
||||
);
|
||||
files_to_remove.extend(&snapshot.levels[task.lower_level - 1].1);
|
||||
snapshot.levels[task.lower_level - 1].1 = output.to_vec();
|
||||
(snapshot, files_to_remove)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user