refactor benchmarks code

This commit is contained in:
Mazdak Farrokhzad 2022-07-27 19:40:19 +02:00
parent 9dd45c3620
commit 86ae9e1727
2 changed files with 86 additions and 147 deletions

View File

@ -18,10 +18,7 @@
use leo_compiler::Compiler; use leo_compiler::Compiler;
use leo_errors::emitter::{Emitter, Handler}; use leo_errors::emitter::{Emitter, Handler};
use leo_span::{ use leo_span::{source_map::FileName, symbol::SESSION_GLOBALS};
source_map::FileName,
symbol::{SessionGlobals, SESSION_GLOBALS},
};
use leo_test_framework::get_benches; use leo_test_framework::get_benches;
use criterion::{black_box, criterion_group, criterion_main, Criterion}; use criterion::{black_box, criterion_group, criterion_main, Criterion};
@ -110,171 +107,113 @@ impl Sample {
} }
} }
fn bench_parse(&self, c: &mut Criterion) { /// Benchmarks `logic(compiler)` where `compiler` is provided.
c.bench_function(&format!("parse {}", self.name), |b| { fn bencher(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler) -> Duration) {
c.bench_function(&format!("{} {}", mode, self.name), |b| {
// Iter custom is used so we can use custom timings around the compiler stages. // Iter custom is used so we can use custom timings around the compiler stages.
// This way we can only time the necessary stage. // This way we can only time the necessary stage.
b.iter_custom(|iters| { b.iter_custom(|iters| {
let mut time = Duration::default(); (0..iters)
for _ in 0..iters { .map(|_| SESSION_GLOBALS.set(&<_>::default(), || logic(new_compiler(&BufEmitter::new_handler()))))
SESSION_GLOBALS.set(&SessionGlobals::default(), || { .sum()
let handler = BufEmitter::new_handler(); });
let mut compiler = new_compiler(&handler);
let (input, name) = self.data();
let start = Instant::now();
let out = compiler.parse_program_from_string(input, name);
time += start.elapsed();
out.expect("Failed to parse program")
});
}
time
})
}); });
} }
/// Benchmarks `logic(compiler)` where `compiler` is provided.
/// Parsing has already been done.
fn bencher_after_parse(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler) -> Duration) {
self.bencher(c, mode, |mut compiler| {
let (input, name) = self.data();
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
logic(compiler)
});
}
fn bench_parse(&self, c: &mut Criterion) {
self.bencher(c, "parse", |mut compiler| {
let (input, name) = self.data();
let start = Instant::now();
let out = compiler.parse_program_from_string(input, name);
let time = start.elapsed();
out.expect("Failed to parse program");
time
})
}
fn bench_symbol_table(&self, c: &mut Criterion) { fn bench_symbol_table(&self, c: &mut Criterion) {
c.bench_function(&format!("symbol table pass {}", self.name), |b| { self.bencher_after_parse(c, "symbol table pass", |compiler| {
// Iter custom is used so we can use custom timings around the compiler stages. let start = Instant::now();
// This way we can only time the necessary stage. let out = compiler.symbol_table_pass();
b.iter_custom(|iters| { let time = start.elapsed();
let mut time = Duration::default(); out.expect("failed to generate symbol table");
for _ in 0..iters { time
SESSION_GLOBALS.set(&SessionGlobals::default(), || {
let handler = BufEmitter::new_handler();
let mut compiler = new_compiler(&handler);
let (input, name) = self.data();
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
let start = Instant::now();
let out = compiler.symbol_table_pass();
time += start.elapsed();
out.expect("failed to generate symbol table");
});
}
time
})
}); });
} }
fn bench_type_checker(&self, c: &mut Criterion) { fn bench_type_checker(&self, c: &mut Criterion) {
c.bench_function(&format!("type checker pass {}", self.name), |b| { self.bencher_after_parse(c, "type checker pass", |compiler| {
// Iter custom is used so we can use custom timings around the compiler stages. let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
// This way we can only time the necessary stage. let start = Instant::now();
b.iter_custom(|iters| { let out = compiler.type_checker_pass(symbol_table);
let mut time = Duration::default(); let time = start.elapsed();
for _ in 0..iters { out.expect("failed to run type check pass");
SESSION_GLOBALS.set(&SessionGlobals::default(), || { time
let handler = BufEmitter::new_handler();
let mut compiler = new_compiler(&handler);
let (input, name) = self.data();
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let start = Instant::now();
let out = compiler.type_checker_pass(symbol_table);
time += start.elapsed();
out.expect("failed to run type check pass")
});
}
time
})
}); });
} }
fn bench_loop_unroller(&self, c: &mut Criterion) { fn bench_loop_unroller(&self, c: &mut Criterion) {
c.bench_function(&format!("loop unrolling pass{}", self.name), |b| { self.bencher_after_parse(c, "loop unrolling pass", |mut compiler| {
// Iter custom is used so we can use custom timings around the compiler stages. let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
// This way we can only time the necessary stage. let symbol_table = compiler
b.iter_custom(|iters| { .type_checker_pass(symbol_table)
let mut time = Duration::default(); .expect("failed to run type check pass");
for _ in 0..iters { let start = Instant::now();
SESSION_GLOBALS.set(&SessionGlobals::default(), || { let out = compiler.loop_unrolling_pass(symbol_table);
let handler = BufEmitter::new_handler(); let time = start.elapsed();
let mut compiler = new_compiler(&handler); out.expect("failed to run loop unrolling pass");
let (input, name) = self.data(); time
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let symbol_table = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let start = Instant::now();
let out = compiler.loop_unrolling_pass(symbol_table);
time += start.elapsed();
out.expect("failed to run loop unrolling pass")
});
}
time
})
}); });
} }
fn bench_ssa(&self, c: &mut Criterion) { fn bench_ssa(&self, c: &mut Criterion) {
c.bench_function(&format!("full {}", self.name), |b| { self.bencher_after_parse(c, "full", |mut compiler| {
// Iter custom is used so we can use custom timings around the compiler stages. let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
// This way we can only time the necessary stages. let symbol_table = compiler
b.iter_custom(|iters| { .type_checker_pass(symbol_table)
let mut time = Duration::default(); .expect("failed to run type check pass");
for _ in 0..iters { compiler
SESSION_GLOBALS.set(&SessionGlobals::default(), || { .loop_unrolling_pass(symbol_table)
let handler = BufEmitter::new_handler(); .expect("failed to run loop unrolling pass");
let mut compiler = new_compiler(&handler); let start = Instant::now();
let (input, name) = self.data(); let out = compiler.static_single_assignment_pass();
compiler let time = start.elapsed();
.parse_program_from_string(input, name) out.expect("failed to run ssa pass");
.expect("Failed to parse program"); time
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table"); })
let symbol_table = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let start = Instant::now();
let out = compiler.static_single_assignment_pass();
time += start.elapsed();
out.expect("failed to run ssa pass")
});
}
time
})
});
} }
fn bench_full(&self, c: &mut Criterion) { fn bench_full(&self, c: &mut Criterion) {
c.bench_function(&format!("full {}", self.name), |b| { self.bencher(c, "full", |mut compiler| {
// Iter custom is used so we can use custom timings around the compiler stages. let (input, name) = self.data();
// This way we can only time the necessary stages. let start = Instant::now();
b.iter_custom(|iters| { compiler
let mut time = Duration::default(); .parse_program_from_string(input, name)
for _ in 0..iters { .expect("Failed to parse program");
SESSION_GLOBALS.set(&SessionGlobals::default(), || { let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let handler = BufEmitter::new_handler(); let symbol_table = compiler
let mut compiler = new_compiler(&handler); .type_checker_pass(symbol_table)
let (input, name) = self.data(); .expect("failed to run type check pass");
let start = Instant::now(); compiler
compiler .loop_unrolling_pass(symbol_table)
.parse_program_from_string(input, name) .expect("failed to run loop unrolling pass");
.expect("Failed to parse program"); compiler
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table"); .static_single_assignment_pass()
let symbol_table = compiler .expect("failed to run ssa pass");
.type_checker_pass(symbol_table) start.elapsed()
.expect("failed to run type check pass"); })
compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
compiler
.static_single_assignment_pass()
.expect("failed to run ssa pass");
time += start.elapsed();
});
}
time
})
});
} }
} }