Skip to content

Conversation

hinto-janai
Copy link
Contributor

@hinto-janai hinto-janai commented Jun 26, 2024

What

Closes #193.

This implements a very minimal benches/:

  • Adds documentation to the architecture book
  • Implements a basic cuprate-benchmark[-lib,-example]
  • Implements cuprate-{example,json-rpc} criterion benchmarks

When, Why, How, Future

See #193.

Plot examples

Here's some plots Criterion generates, taken from #322:

image

Improvement/regression data:

image

@hinto-janai hinto-janai added A-storage Area: Related to storage. A-rpc Area: Related to RPC. labels Jun 26, 2024
@github-actions github-actions bot added A-docs Area: Related to documentation. A-benches Area: Related to benchmarks. and removed A-storage Area: Related to storage. A-rpc Area: Related to RPC. labels Jun 26, 2024
@github-actions github-actions bot added A-dependency Area: Related to dependencies, or changes to a Cargo.{toml,lock} file. A-workspace Area: Changes to a root workspace file or general repo file. labels Jun 26, 2024
@hinto-janai hinto-janai changed the title benches: setup README & harness, add micro/macro examples benches: README, harness, and examples Jun 26, 2024
@hinto-janai hinto-janai mentioned this pull request Jul 1, 2024
28 tasks
@github-actions github-actions bot added A-books Area: Related to Cuprate's books. A-book-architecture Area: Related to the Architecture book. labels Oct 8, 2024
@hinto-janai hinto-janai changed the title benches: README, harness, and examples benches: initial implementation Oct 8, 2024
Copy link
Contributor Author

@hinto-janai hinto-janai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gist of this PR:

2 types of benchmarks exist:

  • Micro benchmarks: Criterion-based
  • Macro benchmarks: cuprate-benchmark benchmarks

Criterion benchmarks are just another crate that uses Criterion.

cuprate-benchmark benchmarks are also kind of simple, they just implement cuprate_benchmark_lib::Benchmark and can be ran by cuprate_benchmark.

Comment on lines 5 to 42
/// A benchmarking function and its inputs.
pub trait Benchmark {
/// The benchmark's name.
///
/// This is automatically implemented
/// as the name of the [`Self`] type.
fn name() -> &'static str {
std::any::type_name::<Self>()
}

/// Input to the main benchmarking function.
///
/// This is passed to [`Self::MAIN`].
type Input;

/// Setup function to generate the input.
///
/// This function is not timed.
const SETUP: fn() -> Self::Input;

/// The main function to benchmark.
///
/// The start of the timer begins right before
/// this function is called and ends after the
/// function returns.
const MAIN: fn(Self::Input);

/// `cuprate-benchmark` will sleep for this [`Duration`] after
/// creating the [`Self::Input`], but before starting [`Self::MAIN`].
///
/// 1 second by default.
const PRE_SLEEP_DURATION: Duration = Duration::from_secs(1);

/// `cuprate-benchmark` will sleep for this [`Duration`] after [`Self::MAIN`].
///
/// 1 second by default.
const POST_SLEEP_DURATION: Duration = Duration::from_secs(1);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For cuprate-benchmark benchmarks, they are just another crate that implements cuprate_benchmark_lib::Benchmark, then...

Comment on lines 14 to 41
/// What `main()` does:
/// 1. Run all enabled benchmarks
/// 2. Record benchmark timings
/// 3. Print timing data
///
/// To add a new benchmark to be ran here:
/// 1. Copy + paste a `cfg_if` block
/// 2. Change it to your benchmark's feature flag
/// 3. Change it to your benchmark's type
fn main() {
log::init_logger();

let mut timings = timings::Timings::new();

cfg_if! {
if #[cfg(not(any(feature = "example")))] {
compile_error!("No feature specified. Use `--features $BENCHMARK_FEATURE` when building.");
}
}

cfg_if! {
if #[cfg(feature = "example")] {
run::run_benchmark::<cuprate_benchmark_example::Example>(&mut timings);
}
}

print::print_timings(&timings);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...are ran in cuprate_benchmark, which currently simply:

  1. Sets up inputs
  2. Starts a timer
  3. Runs benchmark

for each benchmark, prints some data. What this looks like right now:

cargo r -rp cuprate-benchmark --features example
    Finished `release` profile [optimized] target(s) in 0.09s
     Running `target/release/cuprate-benchmark

2024-10-10T00:01:07.701083Z  INFO cuprate_benchmark::log: Log level: INFO
2024-10-10T00:01:08.830698Z  INFO run_benchmark: cuprate_benchmark::run: cuprate_benchmark_example::Example ... 0.12949288

Finished all benchmarks, printing results:

| Benchmark                          | Time (seconds) |
|------------------------------------|----------------|
| cuprate_benchmark_example::Example | 0.12949288     |

Comment on lines +38 to +42
impl Benchmark for Example {
type Input = ExampleBenchmarkInput;
const SETUP: fn() -> Self::Input = example_benchmark_setup;
const MAIN: fn(Self::Input) = example_benchmark_main;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very simple example cuprate-benchmark benchmark.

Comment on lines +146 to +152
- [🟢 Benchmarking](benchmarking/intro.md)
- [🟢 Criterion](benchmarking/criterion/intro.md)
- [🟢 Creating](benchmarking/criterion/creating.md)
- [🟢 Running](benchmarking/criterion/running.md)
- [🟢 `cuprate-benchmark`](benchmarking/cuprate/intro.md)
- [🟢 Creating](benchmarking/cuprate/creating.md)
- [🟢 Running](benchmarking/cuprate/running.md)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More details on benchmarks are here.

@hinto-janai hinto-janai marked this pull request as ready for review October 10, 2024 00:13
@hinto-janai hinto-janai requested a review from Boog900 October 10, 2024 00:13
this `cfg()` existing makes a regular workspace `cargo b` fail
Copy link
Member

@Boog900 Boog900 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, sorry for taking so long. Just a couple nits

Comment on lines 31 to 32
cuprate-benchmark-lib = { path = "../lib" }
cuprate-benchmark-example = { path = "../example", optional = true }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these be added to the workspace so we can do workspace = true

@hinto-janai hinto-janai requested a review from Boog900 November 25, 2024 19:35
@Boog900 Boog900 merged commit caa08d5 into Cuprate:main Nov 25, 2024
7 checks passed
@hinto-janai hinto-janai deleted the benches branch November 25, 2024 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-benches Area: Related to benchmarks. A-book-architecture Area: Related to the Architecture book. A-books Area: Related to Cuprate's books. A-dependency Area: Related to dependencies, or changes to a Cargo.{toml,lock} file. A-docs Area: Related to documentation. A-workspace Area: Changes to a root workspace file or general repo file.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Formalizing benches/

2 participants