Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
PSeitz committed Sep 30, 2024
1 parent 679f74f commit b4a73b5
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 30 deletions.
12 changes: 7 additions & 5 deletions src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ impl<'a, I, O> NamedBench<'a, I, O> {
num_iter: usize,
events: &mut EventManager,
) -> RunResult<O> {
events.emit(BingganEvents::BenchStart(&self.bench_id));
events.emit(BingganEvents::BenchStart {
bench_id: &self.bench_id,
});
let start = std::time::Instant::now();
let mut res = None;
for _ in 0..num_iter {
Expand All @@ -222,10 +224,10 @@ impl<'a, I, O> NamedBench<'a, I, O> {
let elapsed = start.elapsed();

let run_result = RunResult::new(elapsed.as_nanos() as u64 / num_iter as u64, res);
events.emit(BingganEvents::BenchStop(
&self.bench_id,
run_result.duration_ns,
));
events.emit(BingganEvents::BenchStop {
bench_id: &self.bench_id,
duration: run_result.duration_ns,
});
run_result
}
}
11 changes: 8 additions & 3 deletions src/bench_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl BenchRunner {
}

/// Returns the event manager, which can be used to add listeners to the benchmarks.
/// See [EventManager] for more information.
/// See [crate::plugins::EventManager] for more information.
pub fn get_event_manager(&mut self) -> &mut EventManager {
&mut self.listeners
}
Expand Down Expand Up @@ -159,8 +159,12 @@ impl BenchRunner {
}
}

self.listeners.emit(BingganEvents::GroupStart {
runner_name: self.name.as_deref(),
group_name,
output_value_column_title,
});
if let Some(name) = &group_name {
self.listeners.emit(BingganEvents::GroupStart(name));
println!("{}", name.black().on_yellow().invert().bold());
}

Expand Down Expand Up @@ -191,6 +195,7 @@ impl BenchRunner {
}

report_group(
self.name.as_deref(),
group_name,
group,
&*self.reporter,
Expand Down Expand Up @@ -327,7 +332,7 @@ fn round_up(num: u64) -> u64 {
divisor *= 10;
}

num.div_ceil(divisor)
num.div_ceil(divisor) * divisor
}

pub fn minmax<I, T>(mut vals: I) -> Option<(T, T)>
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! - **[BenchRunner]**: A main runner for. Useful for single benchmarks or to create groups.
//! - **[InputGroup]**: Use this when running a group of benchmarks with the same inputs, where ownership of inputs can be transferred.
//!
//! Otherwise if you need more flexibility you can use [BenchGroup] via [BenchRunner::new_group_with_name](crate::BenchRunner::new_group_with_name).
//! Otherwise if you need more flexibility you can use [BenchGroup] via [BenchRunner::new_group](crate::BenchRunner::new).
//!
//! See <https://github.com/PSeitz/binggan/tree/main/benches> for examples. `benches/bench_group.rs` and
//! `benches/bench_input_group.rs` are different ways to produce the same output.
Expand Down Expand Up @@ -166,7 +166,8 @@ pub(crate) mod bench;
pub(crate) mod bench_id;
pub(crate) mod bench_runner;
pub(crate) mod output_value;
pub(crate) mod plugins;
/// The module to define custom plugins
pub mod plugins;
pub use output_value::OutputValue;
/// The module to report benchmark results
pub mod report;
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{

/// Integration via EventListener
/// tracks the max memory consumption per bench
pub struct AllocPerBench {
pub(crate) struct AllocPerBench {
alloc_per_bench: PerBenchData<Vec<usize>>,
alloc: &'static dyn PeakMemAllocTrait,
}
Expand Down Expand Up @@ -39,11 +39,11 @@ impl EventListener for AllocPerBench {
}
fn on_event(&mut self, event: BingganEvents) {
match event {
BingganEvents::BenchStart(bench_id) => {
BingganEvents::BenchStart { bench_id } => {
self.alloc_per_bench.insert_if_absent(bench_id, Vec::new);
self.alloc.reset_peak_memory();
}
BingganEvents::BenchStop(bench_id, _) => {
BingganEvents::BenchStop { bench_id, .. } => {
let perf = self.alloc_per_bench.get_mut(bench_id).unwrap();
perf.push(self.alloc.get_peak_memory());
}
Expand Down
93 changes: 82 additions & 11 deletions src/plugins/events.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,106 @@
use std::any::Any;

use rustc_hash::FxHashMap;
//! Event manager for Binggan.
//! The event manager is responsible for managing event listeners and emitting events.
//! It is used to notify listeners about events that occur during the benchmark run.
//!
//! # Example
//! ```rust no_run
//! use binggan::plugins::*;
//!
//! struct MyListener;
//!
//! impl EventListener for MyListener {
//! fn name(&self) -> &'static str {
//! "my_listener"
//! }
//! fn on_event(&mut self, event: BingganEvents) {
//! match event {
//! BingganEvents::GroupStart{runner_name, ..} => {
//! println!("Starting: {:?}", runner_name);
//! }
//! _ => {}
//! }
//! }
//! fn as_any(&mut self) -> &mut dyn std::any::Any {
//! self
//! }
//! }
//!
//! let mut event_manager = EventManager::new();
//! event_manager.add_listener_if_absent(MyListener);
//! event_manager.emit(BingganEvents::GroupStart{runner_name: Some("test"), group_name: None, output_value_column_title: "output"});
//! ```
//!
//! See the `BingganEvents` enum for the list of events that can be emitted.
//! Any type that implements the `EventListener` trait can be added to the event manager.
//!
use crate::{bench::BenchResult, bench_id::BenchId};
use rustc_hash::FxHashMap;
use std::any::Any;

/// Events that can be emitted by the benchmark runner.
#[derive(Debug, Clone, Copy)]
pub enum BingganEvents<'a> {
/// Parameter is the name of the run
StartRun(&'a str),
/// Parameter is the name of the benchmark group
GroupStart(&'a str),
/// Profiling of the group started
GroupStart {
/// The name of the runner
runner_name: Option<&'a str>,
/// The name of the group
group_name: Option<&'a str>,
/// The name of the column of the output value.
output_value_column_title: &'static str,
},
/// Profiling of the group finished.
GroupStop {
name: Option<&'a str>,
/// The name of the runner
runner_name: Option<&'a str>,
/// The name of the group
group_name: Option<&'a str>,
/// The results of the group
/// This will include the results of all the benchmarks in the group.
/// It also contains delta information of the last run if available
results: &'a [BenchResult],
/// The name of the column of the output value.
output_value_column_title: &'static str,
},
/// The benchmark is started. Note that a benchmark can be run multiple times for higher
/// A benchmark in a group is started. Note that a benchmark can be run multiple times for higher
/// accuracy. BenchStart and BenchStop are not called for each iteration.
///
BenchStart(&'a BenchId),
BenchStop(&'a BenchId, u64),
/// A group is iterated multiple times. This will be called for every iteration in the group.
BenchStart {
/// The bench id
bench_id: &'a BenchId,
},
/// A benchmark in a group is stopped.
BenchStop {
/// The bench id
bench_id: &'a BenchId,
/// The duration of the benchmark
duration: u64,
},
}

/// The trait for listening to events emitted by the benchmark runner.
pub trait EventListener: Any {
/// The name of the event listener.
fn name(&self) -> &'static str;
/// Handle an event.
/// See the [BingganEvents] enum for the list of events that can be emitted.
fn on_event(&mut self, event: BingganEvents);
/// Downcast the listener to `Any`.
fn as_any(&mut self) -> &mut dyn Any;
}

/// The event manager is responsible for managing event listeners and emitting events.
/// It is used to notify listeners about events that occur during the benchmark run.
///
/// See the `BingganEvents` enum for the list of events that can be emitted.
/// Any type that implements the `EventListener` trait can be added to the event manager.
pub struct EventManager {
listeners: Vec<(String, Box<dyn EventListener>)>,
}
impl EventManager {
/// Create a new instance of `EventManager`.
pub fn new() -> Self {
Self {
listeners: Vec::new(),
Expand All @@ -59,6 +124,7 @@ impl EventManager {
.map(|(_, l)| l)
}

/// Downcast a listener to a specific type.
pub fn downcast_listener<T: 'static>(&mut self, name: &str) -> Option<&mut T> {
self.get_listener(name)?.as_any().downcast_mut::<T>()
}
Expand All @@ -68,6 +134,7 @@ impl EventManager {
self.listeners.retain(|(n, _)| n != name);
}

/// Emit an event to all listeners.
pub fn emit(&mut self, event: BingganEvents) {
for (_, listener) in self.listeners.iter_mut() {
listener.on_event(event);
Expand All @@ -91,17 +158,21 @@ impl<T> Default for PerBenchData<T> {
}
}
impl<T> PerBenchData<T> {
/// Create a new instance of `PerBenchData`.
pub fn new() -> Self {
Self {
per_bench_data: FxHashMap::default(),
}
}
/// Get a mutable reference to the data for a specific bench id.
pub fn get_mut(&mut self, bench_id: &BenchId) -> Option<&mut T> {
self.per_bench_data.get_mut(bench_id)
}
/// Get a reference to the data for a specific bench id.
pub fn get(&self, bench_id: &BenchId) -> Option<&T> {
self.per_bench_data.get(bench_id)
}
/// Insert data for a specific bench id if it is not already present.
pub fn insert_if_absent<F: FnOnce() -> T>(&mut self, bench_id: &BenchId, data: F) {
if !self.per_bench_data.contains_key(bench_id) {
self.per_bench_data.insert(bench_id.clone(), data());
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod alloc;
pub(crate) mod events;
pub mod profiler;
pub(crate) mod alloc;
pub mod events;
pub(crate) mod profiler;
pub use events::*;
4 changes: 2 additions & 2 deletions src/plugins/profiler/perf_profiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ impl EventListener for PerfCounterPerBench {
}
fn on_event(&mut self, event: BingganEvents) {
match event {
BingganEvents::BenchStart(bench_id) => {
BingganEvents::BenchStart { bench_id } => {
self.perf_per_bench
.insert_if_absent(bench_id, || PerfCounters::new().ok());
let perf = self.perf_per_bench.get_mut(bench_id).unwrap();
if let Some(perf) = perf {
perf.enable();
}
}
BingganEvents::BenchStop(bench_id, _) => {
BingganEvents::BenchStop { bench_id, .. } => {
let perf = self.perf_per_bench.get_mut(bench_id).unwrap();
if let Some(perf) = perf {
perf.disable();
Expand Down
4 changes: 3 additions & 1 deletion src/report/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub trait ReporterClone {
}

pub(crate) fn report_group<'a>(
runner_name: Option<&str>,
group_name: Option<&str>,
benches: &mut [Box<dyn Bench<'a> + 'a>],
reporter: &dyn Reporter,
Expand All @@ -57,7 +58,8 @@ pub(crate) fn report_group<'a>(
results.push(result);
}
events.emit(BingganEvents::GroupStop {
name: group_name,
runner_name,
group_name,
results: &results,
output_value_column_title,
});
Expand Down

0 comments on commit b4a73b5

Please sign in to comment.