@@ -12,7 +12,7 @@ use serde::Serialize;
1212use 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+
129134pub 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+
344365fn 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-
479476fn 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<(),
527524fn 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+
644677fn 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