Skip to content
Snippets Groups Projects
Verified Commit 71a0260f authored by STEVAN Antoine's avatar STEVAN Antoine :crab:
Browse files

remove quiet and merge functions

parent e74726ae
No related branches found
No related tags found
No related merge requests found
......@@ -2,27 +2,7 @@ use clap::Parser;
use rand::Rng;
fn arithmetic(b: &plnk::Bencher) {
plnk::bench(b, plnk::label! { operation: "addition" }, || {
let a = rand::thread_rng().gen::<u128>();
let b = rand::thread_rng().gen::<u128>();
plnk::timeit(|| a + b)
});
plnk::bench(b, plnk::label! { operation: "substraction" }, || {
let a = rand::thread_rng().gen::<u128>();
let b = rand::thread_rng().gen::<u128>();
plnk::timeit(|| a - b)
});
let res = plnk::bench_and_return(b, plnk::label! { operation: "multiplication" }, || {
let a = rand::thread_rng().gen::<u128>();
let b = rand::thread_rng().gen::<u128>();
plnk::timeit_and_return(|| a * b)
});
eprintln!("last value: {}", res.unwrap());
}
fn arithmetic_multiple(b: &plnk::Bencher) {
plnk::bench_multiple(
let res = plnk::bench_multiple(
b,
vec![
(
......@@ -30,11 +10,11 @@ fn arithmetic_multiple(b: &plnk::Bencher) {
Box::new(|| {
let a = rand::thread_rng().gen::<u128>();
let b = rand::thread_rng().gen::<u128>();
plnk::timeit(|| a - b)
plnk::timeit(|| a + b)
}),
),
(
plnk::label! { operation: "substraction" }.to_string(),
plnk::label! { operation: "subtraction" }.to_string(),
Box::new(|| {
let a = rand::thread_rng().gen::<u128>();
let b = rand::thread_rng().gen::<u128>();
......@@ -50,13 +30,17 @@ fn arithmetic_multiple(b: &plnk::Bencher) {
}),
),
],
)
);
eprintln!("last value: {}", res.unwrap());
}
fn random(b: &plnk::Bencher) {
plnk::bench(b, plnk::label! { operation: "sampling" }, || {
plnk::timeit(|| rand::thread_rng().gen::<u128>())
});
plnk::bench(
b,
plnk::label! { operation: "sampling" },
Box::new(|| plnk::timeit(|| rand::thread_rng().gen::<u128>())),
);
}
#[derive(Parser, Debug)]
......@@ -64,9 +48,6 @@ struct Args {
#[arg(short, long, default_value_t = 10)]
nb_measurements: usize,
#[arg(short, long)]
multiple: bool,
#[arg(short, long)]
log_file: Option<String>,
}
......@@ -81,10 +62,6 @@ fn main() {
None => plnk::Bencher::new(args.nb_measurements),
};
if args.multiple {
arithmetic_multiple(&bencher.with_name("arithmetic"));
} else {
arithmetic(&bencher.with_name("arithmetic"));
}
random(&bencher.with_name("random").append());
}
......@@ -17,8 +17,6 @@ pub struct Bencher {
/// the name of the benchmark
name: String,
quiet: bool,
file: Option<PathBuf>,
append: bool,
}
......@@ -28,7 +26,6 @@ impl Bencher {
Self {
nb_measurements,
name: "".to_string(),
quiet: false,
file: None,
append: false,
}
......@@ -39,7 +36,6 @@ impl Bencher {
Self {
nb_measurements: self.nb_measurements,
name: name.to_string(),
quiet: self.quiet,
file: self.file.clone(),
append: self.append,
}
......@@ -50,7 +46,6 @@ impl Bencher {
Self {
nb_measurements: self.nb_measurements,
name: self.name.clone(),
quiet: self.quiet,
file: Some(path),
append: self.append,
}
......@@ -60,7 +55,6 @@ impl Bencher {
Self {
nb_measurements: self.nb_measurements,
name: self.name.clone(),
quiet: self.quiet,
file: self.file.clone(),
append: true,
}
......@@ -70,95 +64,65 @@ impl Bencher {
Self {
nb_measurements: self.nb_measurements,
name: self.name.clone(),
quiet: self.quiet,
file: self.file.clone(),
append: false,
}
}
/// makes the bencher quiet
pub fn quiet(&self) -> Self {
let mut ret = self.clone();
ret.quiet = true;
ret
}
/// makes the bencher verbose
pub fn verbose(&self) -> Self {
let mut ret = self.clone();
ret.quiet = false;
ret
}
}
#[macro_export]
macro_rules! label {
( $( $key:ident : $value:expr ),* $(,)? ) => {{
let mut parts = Vec::new();
$(
parts.push(format!("{}: {:?}", stringify!($key), $value));
)*
&format!("{{{}}}", parts.join(", "))
}};
}
/// run a given piece of code a bunch of times and output the measurements
///
/// - label: an additional label to differentiate similar but different things to benchmark in the
/// same bencher
/// - f: the piece of code to run and measure
/// - the measurements will be printed to STDOUT as JSON
pub fn bench<F>(b: &Bencher, label: &str, f: F)
where
F: Fn() -> Duration,
{
if !b.quiet {
eprintln!("bencher: {}, label: {}", b.name, label);
}
let pb = ProgressBar::new(b.nb_measurements as u64)
.with_style(ProgressStyle::default_bar().progress_chars("#*-"));
let mut times = vec![];
for _ in 0..b.nb_measurements {
times.push(f().as_nanos());
pb.inc(1);
}
let output = format!("{}", label! { label: label, name: b.name, times: times });
if let Some(path) = &b.file {
fn dump(&self, label: &str, times: &[u128], append: bool) {
let output = format!("{}", label! { label: label, name: self.name, times: times });
if let Some(path) = &self.file {
create_dir_all(path.parent().unwrap()).expect(&format!(
"could not create parent directory of log file '{}'",
"{}: could not create parent directory of log file '{}'",
self.name,
path.to_str().unwrap()
));
let mut f = File::options()
.write(true)
.append(b.append)
.truncate(!b.append)
.append(append)
.truncate(!append)
.create(true)
.open(path)
.expect(&format!(
"could not open log file '{}'",
"{}: could not open log file '{}'",
self.name,
path.to_str().unwrap()
));
writeln!(&mut f, "{}", output).expect(&format!(
"could not write to log file '{}'",
"{}: could not write to log file '{}'",
self.name,
path.to_str().unwrap()
));
} else {
println!("{}", output);
}
}
}
/// run a given piece of code a bunch of times and output the measurements
#[macro_export]
macro_rules! label {
( $( $key:ident : $value:expr ),* $(,)? ) => {{
let mut parts = Vec::new();
$(
parts.push(format!("{}: {:?}", stringify!($key), $value));
)*
&format!("{{{}}}", parts.join(", "))
}};
}
/// benchmark multiple pieces of code
///
/// - benches is a list of label-f pairs:
/// - label: an additional label to differentiate similar but different things to benchmark in the
/// same bencher
/// - f: the piece of code to run and measure
/// - the measurements will be printed to STDOUT as JSON
/// - the measurements will be printed to STDOUT or to file as JSON
/// - the result of the last run will be returned
#[allow(clippy::type_complexity)]
pub fn bench_multiple(b: &Bencher, benches: Vec<(String, Box<dyn Fn() -> Duration>)>) {
pub fn bench_multiple<O>(
b: &Bencher,
benches: Vec<(String, Box<dyn Fn() -> (Duration, O)>)>,
) -> Option<O> {
let style = ProgressStyle::with_template(
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>10}/{len:10} {msg}",
)
......@@ -170,109 +134,52 @@ pub fn bench_multiple(b: &Bencher, benches: Vec<(String, Box<dyn Fn() -> Duratio
let pb_main = mpb.add(ProgressBar::new(benches.len() as u64).with_style(style.clone()));
pb_main.set_message(b.name.clone());
let mut res = None;
let mut append = b.append;
for (label, f) in benches.iter() {
let pb = mpb.add(ProgressBar::new(b.nb_measurements as u64).with_style(style.clone()));
pb.set_message(label.to_string());
let mut times = vec![];
for _ in 0..b.nb_measurements {
times.push(f().as_nanos());
let (t, _res) = f();
res = Some(_res);
times.push(t.as_nanos());
pb.inc(1);
}
pb_main.inc(1);
pb.finish_and_clear();
let output = format!("{}", label! { label: label, name: b.name, times: times });
if let Some(path) = &b.file {
create_dir_all(path.parent().unwrap()).expect(&format!(
"could not create parent directory of log file '{}'",
path.to_str().unwrap()
));
println!("append: {}", append);
let mut f = File::options()
.write(true)
.append(append)
.truncate(!append)
.create(true)
.open(path)
.expect(&format!(
"could not open log file '{}'",
path.to_str().unwrap()
));
writeln!(&mut f, "{}", output).expect(&format!(
"could not write to log file '{}'",
path.to_str().unwrap()
));
b.dump(label, &times, append);
append = true;
} else {
println!("{}", output);
}
}
pb_main.finish_with_message(format!("{} done", b.name));
res
}
/// run a given piece of code a bunch of times and output the measurements and the last return
/// value
/// benchmark a piece of code
///
/// - label: an additional label to differentiate similar but different things to benchmark in the
/// same bencher
/// - f: the piece of code to run and measure
/// - the measurements will be printed to STDOUT as JSON
pub fn bench_and_return<F, O>(b: &Bencher, label: &str, f: F) -> Option<O>
where
F: Fn() -> (Duration, O),
{
if !b.quiet {
eprintln!("bencher: {}, label: {}", b.name, label);
}
let pb = ProgressBar::new(b.nb_measurements as u64)
.with_style(ProgressStyle::default_bar().progress_chars("#*-"));
let mut res = None;
let mut times = vec![];
for _ in 0..b.nb_measurements {
let (t, _res) = f();
res = Some(_res);
times.push(t.as_nanos());
pb.inc(1);
}
println!("{}", label! { label: label, name: b.name, times: times });
res
}
/// measure the time it takes to do something
///
/// # Example
/// ```rust
/// # use plnk::timeit;
/// let t = timeit(|| 1 + 2);
/// ```
pub fn timeit<F, O>(f: F) -> Duration
where
F: Fn() -> O,
{
let start_time = Instant::now();
let _ = f();
Instant::now().duration_since(start_time)
/// - the measurements will be printed to STDOUT or to file as JSON
/// - the result of the last run will be returned
pub fn bench<O>(b: &Bencher, label: impl ToString, f: Box<dyn Fn() -> (Duration, O)>) -> Option<O> {
bench_multiple(b, vec![(label.to_string(), f)])
}
/// measure the time it takes to do something, and return the result
///
/// # Example
/// ```rust
/// # use plnk::timeit_and_return;
/// let (t, res) = timeit_and_return(|| 1 + 2);
/// # use plnk::timeit;
/// let (t, res) = timeit(|| 1 + 2);
/// assert_eq!(res, 3);
/// ```
pub fn timeit_and_return<F, O>(f: F) -> (Duration, O)
pub fn timeit<F, O>(f: F) -> (Duration, O)
where
F: Fn() -> O,
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment