Skip to content

Commit cc3b58d

Browse files
committed
Add cleanup option to storage footprint benchmark
1 parent 935650e commit cc3b58d

3 files changed

Lines changed: 94 additions & 31 deletions

File tree

docs/BENCHMARKING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cargo bench --bench janusql_live_mqtt_e2e
3535
cargo run --release --bin storage_footprint_benchmark -- \
3636
--event-counts 10000,50000 \
3737
--iterations 1 \
38+
--cleanup-runs-after-measurement \
3839
--output-dir results/storage_footprint_local
3940
```
4041

@@ -61,7 +62,8 @@ CityBench-style RDF events to:
6162

6263
It then flushes and closes the store, measures the full recursive directory size in bytes, and
6364
records ingest time, events per second, and bytes per event. `--include-10m` is required before
64-
running the 10,000,000-event case.
65+
running the 10,000,000-event case. If `--cleanup-runs-after-measurement` is enabled, each
66+
per-run store directory is deleted only after its raw CSV row has been written and flushed.
6567

6668
### `historical_fixed`
6769

src/bin/storage_footprint_benchmark.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ struct Args {
4545
#[arg(long, default_value_t = false)]
4646
include_10m: bool,
4747

48+
#[arg(long, default_value_t = false)]
49+
cleanup_runs_after_measurement: bool,
50+
4851
#[arg(long, value_enum, default_value_t = SystemArg::Both)]
4952
system: SystemArg,
5053

@@ -64,6 +67,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
6467
iterations: args.iterations,
6568
output_dir: output_dir.clone(),
6669
include_10m: args.include_10m,
70+
cleanup_runs_after_measurement: args.cleanup_runs_after_measurement,
6771
system_selection: args.system.into(),
6872
})?;
6973

src/paper_bench/storage_footprint.rs

Lines changed: 87 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use serde::Serialize;
1212
use std::{
1313
collections::BTreeMap,
1414
fs::{self, File},
15-
io::Write,
15+
io::{BufWriter, Write},
1616
path::{Path, PathBuf},
1717
time::Instant,
1818
};
@@ -66,6 +66,7 @@ pub struct StorageFootprintConfig {
6666
pub iterations: usize,
6767
pub output_dir: PathBuf,
6868
pub include_10m: bool,
69+
pub cleanup_runs_after_measurement: bool,
6970
pub system_selection: StorageSystemSelection,
7071
}
7172

@@ -126,6 +127,10 @@ struct RunMeasurement {
126127
path: PathBuf,
127128
}
128129

130+
struct RawCsvWriter {
131+
writer: BufWriter<File>,
132+
}
133+
129134
pub fn run_storage_footprint_benchmark(
130135
config: &StorageFootprintConfig,
131136
) -> Result<StorageFootprintOutcome, BoxError> {
@@ -134,6 +139,8 @@ pub fn run_storage_footprint_benchmark(
134139

135140
let metadata = collect_repro_metadata();
136141
let mut raw_rows = Vec::new();
142+
let raw_csv_path = config.output_dir.join("storage_footprint_raw.csv");
143+
let mut raw_csv_writer = RawCsvWriter::create(&raw_csv_path)?;
137144

138145
for &event_count in &config.event_counts {
139146
for iteration in 1..=config.iterations {
@@ -155,7 +162,7 @@ pub fn run_storage_footprint_benchmark(
155162
0.0
156163
};
157164

158-
raw_rows.push(StorageFootprintRawRow {
165+
let raw_row = StorageFootprintRawRow {
159166
event_count,
160167
iteration,
161168
system: system.as_str().to_string(),
@@ -165,22 +172,25 @@ pub fn run_storage_footprint_benchmark(
165172
load_time_ms: measurement.load_time_ms,
166173
events_per_second,
167174
path: display_path(&measurement.path),
168-
});
175+
};
176+
raw_csv_writer.write_row(&raw_row)?;
177+
if config.cleanup_runs_after_measurement {
178+
cleanup_run_store_dir(&measurement.path)?;
179+
}
180+
raw_rows.push(raw_row);
169181
}
170182
}
171183
}
172184

173185
let summary_rows = summarize_rows(&raw_rows);
174186
let ratio_rows = build_ratio_rows(&summary_rows);
175-
let raw_csv_path = config.output_dir.join("storage_footprint_raw.csv");
176187
let summary_csv_path = config.output_dir.join("storage_footprint_summary.csv");
177188
let ratio_csv_path = config.output_dir.join("storage_footprint_ratio_summary.csv");
178189
let markdown_path = config.output_dir.join("storage_footprint_summary.md");
179190

180-
write_raw_csv(&raw_csv_path, &raw_rows)?;
181191
write_summary_csv(&summary_csv_path, &summary_rows)?;
182192
write_ratio_csv(&ratio_csv_path, &ratio_rows)?;
183-
write_markdown_report(&markdown_path, &metadata, &summary_rows, &ratio_rows)?;
193+
write_markdown_report(&markdown_path, &metadata, config, &summary_rows, &ratio_rows)?;
184194

185195
Ok(StorageFootprintOutcome {
186196
metadata,
@@ -341,6 +351,17 @@ fn event_quads_for_persistent_oxigraph(
341351
Ok([data_quad, timestamp_quad, graph_quad])
342352
}
343353

354+
fn cleanup_run_store_dir(store_dir: &Path) -> Result<(), BoxError> {
355+
fs::remove_dir_all(store_dir).map_err(|err| {
356+
std::io::Error::other(format!(
357+
"failed to remove run store directory {} after persisting raw CSV row: {}",
358+
store_dir.display(),
359+
err
360+
))
361+
})?;
362+
Ok(())
363+
}
364+
344365
fn recursive_dir_size_bytes(root: &Path) -> Result<u64, BoxError> {
345366
let mut total = 0_u64;
346367
for entry in fs::read_dir(root)? {
@@ -452,30 +473,6 @@ fn build_ratio_rows(summary_rows: &[StorageFootprintSummaryRow]) -> Vec<StorageF
452473
.collect()
453474
}
454475

455-
fn write_raw_csv(path: &Path, rows: &[StorageFootprintRawRow]) -> Result<(), BoxError> {
456-
let mut file = File::create(path)?;
457-
writeln!(
458-
file,
459-
"event_count,iteration,system,storage_bytes,storage_mb,bytes_per_event,load_time_ms,events_per_second,path"
460-
)?;
461-
for row in rows {
462-
writeln!(
463-
file,
464-
"{},{},{},{},{:.6},{:.6},{:.3},{:.6},{}",
465-
row.event_count,
466-
row.iteration,
467-
row.system,
468-
row.storage_bytes,
469-
row.storage_mb,
470-
row.bytes_per_event,
471-
row.load_time_ms,
472-
row.events_per_second,
473-
csv_escape(&row.path)
474-
)?;
475-
}
476-
Ok(())
477-
}
478-
479476
fn write_summary_csv(path: &Path, rows: &[StorageFootprintSummaryRow]) -> Result<(), BoxError> {
480477
let mut file = File::create(path)?;
481478
writeln!(
@@ -527,6 +524,7 @@ fn write_ratio_csv(path: &Path, rows: &[StorageFootprintRatioRow]) -> Result<(),
527524
fn write_markdown_report(
528525
path: &Path,
529526
metadata: &ReproMetadata,
527+
config: &StorageFootprintConfig,
530528
summary_rows: &[StorageFootprintSummaryRow],
531529
ratio_rows: &[StorageFootprintRatioRow],
532530
) -> Result<(), BoxError> {
@@ -557,6 +555,11 @@ fn write_markdown_report(
557555
writeln!(file, "- Rust: {}", metadata.rustc_version)?;
558556
writeln!(file, "- OS: {}", metadata.os)?;
559557
writeln!(file, "- CPU: {}", metadata.cpu_model)?;
558+
writeln!(
559+
file,
560+
"- Cleanup runs after measurement: {}",
561+
config.cleanup_runs_after_measurement
562+
)?;
560563
writeln!(
561564
file,
562565
"- RAM bytes: {}",
@@ -641,6 +644,36 @@ fn display_path(path: &Path) -> String {
641644
path.canonicalize().unwrap_or_else(|_| path.to_path_buf()).display().to_string()
642645
}
643646

647+
impl RawCsvWriter {
648+
fn create(path: &Path) -> Result<Self, BoxError> {
649+
let mut writer = BufWriter::new(File::create(path)?);
650+
writeln!(
651+
writer,
652+
"event_count,iteration,system,storage_bytes,storage_mb,bytes_per_event,load_time_ms,events_per_second,path"
653+
)?;
654+
writer.flush()?;
655+
Ok(Self { writer })
656+
}
657+
658+
fn write_row(&mut self, row: &StorageFootprintRawRow) -> Result<(), BoxError> {
659+
writeln!(
660+
self.writer,
661+
"{},{},{},{},{:.6},{:.6},{:.3},{:.6},{}",
662+
row.event_count,
663+
row.iteration,
664+
row.system,
665+
row.storage_bytes,
666+
row.storage_mb,
667+
row.bytes_per_event,
668+
row.load_time_ms,
669+
row.events_per_second,
670+
csv_escape(&row.path)
671+
)?;
672+
self.writer.flush()?;
673+
Ok(())
674+
}
675+
}
676+
644677
fn mean(values: &[f64]) -> f64 {
645678
if values.is_empty() {
646679
0.0
@@ -687,6 +720,7 @@ mod tests {
687720
iterations: 1,
688721
output_dir: output_dir.clone(),
689722
include_10m: false,
723+
cleanup_runs_after_measurement: false,
690724
system_selection: StorageSystemSelection::Both,
691725
})
692726
.expect("small benchmark run should succeed");
@@ -708,10 +742,33 @@ mod tests {
708742
iterations: 1,
709743
output_dir: temp_dir.path().join("guard"),
710744
include_10m: false,
745+
cleanup_runs_after_measurement: false,
711746
system_selection: StorageSystemSelection::Janus,
712747
})
713748
.expect_err("10M run should be rejected without include_10m");
714749

715750
assert!(err.to_string().contains("--include-10m"));
716751
}
752+
753+
#[test]
754+
fn cleanup_enabled_removes_run_store_dirs_but_keeps_result_files() {
755+
let temp_dir = TempDir::new().expect("temp dir should be created");
756+
let output_dir = temp_dir.path().join("storage_footprint_cleanup");
757+
let outcome = run_storage_footprint_benchmark(&StorageFootprintConfig {
758+
event_counts: vec![10],
759+
iterations: 1,
760+
output_dir: output_dir.clone(),
761+
include_10m: false,
762+
cleanup_runs_after_measurement: true,
763+
system_selection: StorageSystemSelection::Both,
764+
})
765+
.expect("cleanup benchmark run should succeed");
766+
767+
assert!(outcome.raw_csv_path.is_file());
768+
assert!(outcome.summary_csv_path.is_file());
769+
assert!(outcome.ratio_csv_path.is_file());
770+
assert!(outcome.markdown_path.is_file());
771+
assert!(!output_dir.join("runs/janus_events_10_iter_1/store").exists());
772+
assert!(!output_dir.join("runs/oxigraph_events_10_iter_1/store").exists());
773+
}
717774
}

0 commit comments

Comments
 (0)