Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(bench)!: move benchmarking facilities to their own crate #208

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ jobs:
- name: clippy
uses: clechasseur/rs-clippy-check@v3
with:
args: --verbose --locked -p riot-rs-embassy
args: --verbose --locked -p riot-rs-embassy -p riot-rs-bench

# TODO: we'll eventually want to enable relevant features
- name: "rustdoc"
run: cargo rustdoc -p riot-rs --features no-boards -- -D warnings
run: cargo rustdoc -p riot-rs --features no-boards,bench -- -D warnings

- name: rustfmt
run: cargo fmt --check --all
Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"src/lib/rbi",
"src/lib/ringbuffer",
"src/riot-rs",
"src/riot-rs-bench",
"src/riot-rs-boards",
"src/riot-rs-boards/nrf52",
"src/riot-rs-boards/nrf52840dk",
Expand Down Expand Up @@ -51,6 +52,7 @@ esp-wifi = { git = "https://github.com/kaspar030/esp-wifi", branch = "update-esp
linkme = { version = "0.3.21", features = ["used_linker"] }

riot-rs = { path = "src/riot-rs", default-features = false }
riot-rs-bench = { path = "src/riot-rs-bench", default-features = false }
riot-rs-boards = { path = "src/riot-rs-boards", default-features = false }
riot-rs-debug = { path = "src/riot-rs-debug", default-features = false }
riot-rs-rt = { path = "src/riot-rs-rt" }
Expand Down
2 changes: 1 addition & 1 deletion examples/benchmark/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ edition = "2021"
publish = false

[dependencies]
riot-rs = { path = "../../src/riot-rs", features = ["threading"] }
riot-rs = { path = "../../src/riot-rs", features = ["bench", "threading"] }
riot-rs-boards = { path = "../../src/riot-rs-boards" }
2 changes: 1 addition & 1 deletion examples/benchmark/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use riot_rs::debug::println;

#[riot_rs::thread(autostart)]
fn main() {
match riot_rs::rt::benchmark(10000, || {
match riot_rs::bench::benchmark(10000, || {
//
}) {
Ok(ticks) => {
Expand Down
15 changes: 15 additions & 0 deletions src/riot-rs-bench/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "riot-rs-bench"
version.workspace = true
authors.workspace = true
edition.workspace = true
repository.workspace = true

[lints]
workspace = true

[dependencies]
cfg-if = { workspace = true }

[target.'cfg(context = "cortex-m")'.dependencies]
cortex-m = { workspace = true, features = ["critical-section-single-core"] }
36 changes: 36 additions & 0 deletions src/riot-rs-bench/src/cortexm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use cortex_m::{
peripheral::{syst::SystClkSource, SYST},
Peripherals,
};

use crate::Error;

#[allow(missing_docs)]
pub fn benchmark<F: Fn() -> ()>(iterations: usize, f: F) -> Result<usize, Error> {
let mut p = unsafe { Peripherals::steal() };
//
p.SCB.clear_sleepdeep();

//
p.SYST.set_clock_source(SystClkSource::Core);
p.SYST.set_reload(0x00FFFFFF);
p.SYST.clear_current();
p.SYST.enable_counter();

// Wait for the system timer to be ready
while SYST::get_current() == 0 {}

let before = SYST::get_current();

for _ in 0..iterations {
f();
}

let total = before - SYST::get_current();

if p.SYST.has_wrapped() {
Err(Error::SystemTimerWrapped)
} else {
Ok(total as usize / iterations)
}
}
55 changes: 55 additions & 0 deletions src/riot-rs-bench/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! Provides on-board benchmarking facilities.

#![cfg_attr(not(test), no_std)]
#![feature(error_in_core)]
#![deny(clippy::pedantic)]
#![deny(missing_docs)]

cfg_if::cfg_if! {
if #[cfg(context = "cortex-m")] {
mod cortexm;
use cortexm as bench;
}
else if #[cfg(context = "riot-rs")] {
// When run with laze but the architecture is not supported
compile_error!("benchmarking is not supported for this architecture");
} else {
// Provide a default bench module, for arch-independent tooling
mod bench {
use crate::Error;

/// Benchmarks "time" required to run the provided function.
///
/// Runs the provided function `iterations` times, and returns the mean number of system timer
/// increments per iteration.
///
/// # Errors
///
/// Returns [`Error::SystemTimerWrapped`] if the system timer counter has wrapped when
/// benchmarking.
#[allow(unused_variables)]
pub fn benchmark<F: Fn()>(iterations: usize, f: F) -> Result<usize, Error> {
unimplemented!();
}
}
}
}

pub use bench::benchmark;

/// Possible errors happening when benchmarking.
#[derive(Debug)]
pub enum Error {
/// The system timer wrapped when benchmarking.
SystemTimerWrapped,
}

impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::SystemTimerWrapped => write!(f, "system timer wrapped"),
}
}
}

impl core::error::Error for Error {}
31 changes: 0 additions & 31 deletions src/riot-rs-rt/src/cortexm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,34 +208,3 @@ pub fn init() {
p.SCB.set_priority(SystemHandler::PendSV, 0xFF);
}
}

pub fn benchmark<F: Fn() -> ()>(iterations: usize, f: F) -> core::result::Result<usize, ()> {
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::Peripherals;

let mut p = unsafe { Peripherals::steal() };
//
p.SCB.clear_sleepdeep();

//
p.SYST.set_clock_source(SystClkSource::Core);
p.SYST.set_reload(0x00FFFFFF);
p.SYST.clear_current();
p.SYST.enable_counter();

while cortex_m::peripheral::SYST::get_current() == 0 {}

let before = cortex_m::peripheral::SYST::get_current();

for _ in 0..iterations {
f();
}

let total = before - cortex_m::peripheral::SYST::get_current();

if p.SYST.has_wrapped() {
Err(())
} else {
Ok((total) as usize / iterations)
}
}
4 changes: 0 additions & 4 deletions src/riot-rs-rt/src/esp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@ fn main() -> ! {
}

pub fn init() {}

pub fn benchmark<F: Fn() -> ()>(_iterations: usize, _f: F) -> core::result::Result<usize, ()> {
unimplemented!()
}
5 changes: 0 additions & 5 deletions src/riot-rs-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,10 @@ cfg_if::cfg_if! {
mod arch {
#[cfg_attr(not(context = "riot-rs"), allow(dead_code))]
pub fn init() {}
pub fn benchmark<F: Fn()>(_iterations: usize, _f: F) -> core::result::Result<usize, ()> {
unimplemented!();
}
}
}
}

pub use arch::benchmark;

const ISR_STACKSIZE: usize =
riot_rs_utils::usize_from_env_or!("CONFIG_ISR_STACKSIZE", 8192, "ISR stack size (in bytes)");

Expand Down
3 changes: 3 additions & 0 deletions src/riot-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ workspace = true
[dependencies]
document-features = { workspace = true }
linkme = { workspace = true }
riot-rs-bench = { workspace = true, optional = true }
riot-rs-boards = { path = "../riot-rs-boards" }
riot-rs-buildinfo = { path = "../riot-rs-buildinfo" }
riot-rs-debug = { workspace = true }
Expand Down Expand Up @@ -74,6 +75,8 @@ wifi-esp = ["riot-rs-embassy/wifi-esp"]
## Enables the debug console, required to use
## [`println!`](riot_rs_debug::println).
debug-console = ["riot-rs-rt/debug-console"]
## Enables benchmarking facilities.
bench = ["dep:riot-rs-bench"]
## Prints nothing in case of panics (may help reduce binary size).
silent-panic = ["riot-rs-rt/silent-panic"]
## Allows to have no boards selected, useful to run target-independent tooling.
Expand Down
4 changes: 4 additions & 0 deletions src/riot-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
#![no_std]
#![feature(doc_cfg)]

#[cfg(feature = "bench")]
kaspar030 marked this conversation as resolved.
Show resolved Hide resolved
#[doc(cfg(feature = "bench"))]
#[doc(inline)]
pub use riot_rs_bench as bench;
pub use riot_rs_buildinfo as buildinfo;
pub use riot_rs_debug as debug;
pub use riot_rs_embassy::{self as embassy, define_peripherals, group_peripherals};
Expand Down
1 change: 1 addition & 0 deletions tests/benchmarks/bench_sched_yield/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ publish = false

[dependencies]
riot-rs = { workspace = true, default-features = true, features = [
"bench",
"threading",
] }
riot-rs-boards = { workspace = true }
2 changes: 1 addition & 1 deletion tests/benchmarks/bench_sched_yield/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use riot_rs::{debug::println, thread};

#[riot_rs::thread(autostart)]
fn thread0() {
match riot_rs::rt::benchmark(10000, || thread::yield_same()) {
match riot_rs::bench::benchmark(10000, || thread::yield_same()) {
Ok(ticks) => {
println!(
"took {} ticks per iteration ({} per context switch)",
Expand Down