### Automate Gungraun Runner Installation in CI (GitHub Actions) Source: https://gungraun.github.io/gungraun/latest/html/installation/gungraun Provides examples of GitHub Actions CI job steps to automate the installation of the `gungraun-runner` binary. These snippets dynamically fetch the `gungraun` library version and install a matching `gungraun-runner`, ensuring version compatibility. ```yaml - name: Install gungraun-runner run: | version=$(cargo metadata --format-version=1 \ jq '.packages[] | select(.name == "gungraun").version' \ tr -d '"' ) cargo install gungraun-runner --version $version ``` ```yaml - uses: taiki-e/install-action@cargo-binstall - name: Install gungraun-runner run: | version=$(cargo metadata --format-version=1 \ jq '.packages[] | select(.name == "gungraun").version' \ tr -d '"' ) cargo binstall --no-confirm gungraun-runner --version $version ``` -------------------------------- ### Example Binary Benchmark Setup Source: https://gungraun.github.io/gungraun/latest/html/print Illustrates how a simple binary's main function can be structured to allow its core logic to be benchmarked as a library function. This approach promotes code reuse and organization for benchmarking. ```rust mod my_lib { pub fn run() {} } use my_lib::run; fn main() { run(); } ``` -------------------------------- ### Install Gungraun Runner Binary (Rust) Source: https://gungraun.github.io/gungraun/latest/html/installation/gungraun Demonstrates various methods to install the `gungraun-runner` binary, which is necessary for running benchmarks. Options include global installation, installation to a specific root directory, and using `binstall` for pre-built binaries. ```bash cargo install --version 0.17.0 gungraun-runner ``` ```bash cargo install --version 0.17.0 --root /tmp gungraun-runner GUNGRAUN_RUNNER=/tmp/bin/gungraun-runner cargo bench --bench my-bench ``` ```bash cargo binstall gungraun-runner@0.17.0 ``` -------------------------------- ### Benchmark Fibonacci Function with Setup Code Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/structure This example shows how to incorporate setup logic into Gungraun benchmarks. The `some_setup_func` is called within the `#[bench]` attribute to prepare input for the benchmarked `fibonacci` function, keeping the benchmark function body clean. This allows for more complex setup without skewing benchmark results. ```rust extern crate gungraun; use gungraun::{main, library_benchmark_group, library_benchmark}; use std::hint::black_box; fn some_setup_func(value: u64) -> u64 { value + 10 } fn fibonacci(n: u64) -> u64 { match n { 0 => 1, 1 => 1, n => fibonacci(n - 1) + fibonacci(n - 2), } } #[library_benchmark] #[bench::short(10)] // Note the usage of the `some_setup_func` in the argument list of this #[bench] #[bench::long(some_setup_func(20))] fn bench_fibonacci(value: u64) -> u64 { black_box(fibonacci(value)) } library_benchmark_group!( name = bench_fibonacci_group; benchmarks = bench_fibonacci ); fn main() { main!(library_benchmark_groups = bench_fibonacci_group); } ``` -------------------------------- ### Static Setup for Binary Benchmark Source: https://gungraun.github.io/gungraun/latest/html/print Demonstrates a basic binary benchmark with a static setup function. The `create_file` function is called before the benchmarked command is executed. Dependencies include the `gungraun` crate. Input is implicitly handled by the setup function creating a file, and the output is a `gungraun::Command`. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main}; fn create_file() { std::fs::write("foo.txt", "some content").unwrap(); } #[binary_benchmark] #[bench::foo(args = ("foo.txt"), setup = create_file())] // Note: setup is called directly fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Install gungraun-runner using binstall Source: https://gungraun.github.io/gungraun/latest/html/print Shows how to install the `gungraun-runner` binary using `cargo binstall`, a tool for easily installing pre-compiled binaries. ```shell cargo binstall gungraun-runner@0.17.0 ``` -------------------------------- ### Gungraun Static Binary Benchmark Setup Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/differences This Rust code demonstrates a basic binary benchmark in Gungraun with a static setup function. The `create_file` function is called before the benchmarked command is executed. The `setup` expression is evaluated and executed just before the benchmarked `Command` is executed. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main}; fn create_file() { std::fs::write("foo.txt", "some content").unwrap(); } #[binary_benchmark] #[bench::foo(args = ("foo.txt"), setup = create_file())] fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Benchmark with Individual Setup Function Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/setup_and_teardown Demonstrates how to use an individual `setup` function (`open_file`) for a specific benchmark (`count_bytes_fast`). The `setup` function prepares arguments (a `File`) for the benchmark function, and its execution time is not included in the benchmark results. ```rust extern crate gungraun; mod my_lib { pub fn count_bytes_fast(_file: std::fs::File) -> u64 { 1 } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; use std::path::PathBuf; use std::fs::File; fn open_file(path: &str) -> File { File::open(path).unwrap() } #[library_benchmark] #[bench::first(args = ("path/to/file"), setup = open_file)] fn count_bytes_fast(file: File) -> u64 { black_box(my_lib::count_bytes_fast(file)) } library_benchmark_group!(name = my_group; benchmarks = count_bytes_fast); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Install gungraun-runner binary Source: https://gungraun.github.io/gungraun/latest/html/print Provides instructions for installing the `gungraun-runner` binary, which is required to run benchmarks. This can be done globally or with a custom root directory. ```shell cargo install --version 0.17.0 gungraun-runner ``` ```shell cargo install --version 0.17.0 --root /tmp gungraun-runner GUNGRAUN_RUNNER=/tmp/bin/gungraun-runner cargo bench --bench my-bench ``` -------------------------------- ### Rust Benchmark with Group-Level Setup Function Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/setup_and_teardown Illustrates applying a default `setup` function (`open_file`) to multiple benchmarks within a `#[library_benchmark]` attribute. It also shows how to override or specify a different setup function (`open_file_with_offset`) for a particular benchmark. ```rust extern crate gungraun; mod my_lib { pub fn count_bytes_fast(_file: std::fs::File) -> u64 { 1 } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; use std::path::PathBuf; use std::fs::File; use std::io::{Seek, SeekFrom}; fn open_file(path: &str) -> File { File::open(path).unwrap() } fn open_file_with_offset(path: &str, offset: u64) -> File { let mut file = File::open(path).unwrap(); file.seek(SeekFrom::Start(offset)).unwrap(); file } #[library_benchmark(setup = open_file)] #[bench::small("path/to/small")] #[bench::big("path/to/big")] #[bench::with_offset(args = ("path/to/big", 100), setup = open_file_with_offset)] fn count_bytes_fast(file: File) -> u64 { black_box(my_lib::count_bytes_fast(file)) } library_benchmark_group!(name = my_group; benchmarks = count_bytes_fast); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Install Valgrind using Package Managers Source: https://gungraun.github.io/gungraun/latest/html/installation/prerequisites Provides commands to install Valgrind, a memory debugging tool essential for Gungraun, across different Linux package managers. Valgrind must be installed and available in the system's PATH for Gungraun to function correctly. Ensure you are using a recent version of Valgrind (>= 3.20.0 recommended). ```shell apk add valgrind ``` ```shell pacman -Sy valgrind ``` ```shell apt-get install valgrind ``` ```shell dnf install valgrind ``` ```shell pkg install valgrind ``` -------------------------------- ### Gungraun Dynamic Binary Benchmark Setup and Teardown Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/differences This Rust code illustrates Gungraun binary benchmarks where `setup` and `teardown` functions receive arguments from the benchmark's `args`. This allows for dynamic setup and cleanup based on the benchmark's parameters. The `setup` and `teardown` functions are called with the `args` value. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main}; fn create_file(path: &str) { std::fs::write(path, "some content").unwrap(); } fn delete_file(path: &str) { std::fs::remove_file(path).unwrap(); } #[binary_benchmark] // Note the missing parentheses for `setup` of the function `create_file` which // tells Gungraun to pass the `args` to the `setup` function AND the // function `bench_binary` #[bench::foo(args = ("foo.txt"), setup = create_file)] // Same for `teardown` #[bench::bar(args = ("bar.txt"), setup = create_file, teardown = delete_file)] fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Automate gungraun-runner installation in GitHub Actions Source: https://gungraun.github.io/gungraun/latest/html/print Example GitHub Actions workflow steps to automatically install the correct version of `gungraun-runner` that matches the `gungraun` library version, ensuring compatibility. It uses `cargo metadata` and `jq` to determine the version. ```yaml - name: Install gungraun-runner run: | version=$(cargo metadata --format-version=1 \ jq '.packages[] | select(.name == "gungraun").version' \ tr -d '"' ) cargo install gungraun-runner --version $version ``` ```yaml - uses: taiki-e/install-action@cargo-binstall - name: Install gungraun-runner run: | version=$(cargo metadata --format-version=1 \ jq '.packages[] | select(.name == "gungraun").version' \ tr -d '"' ) cargo binstall --no-confirm gungraun-runner --version $version ``` -------------------------------- ### Rust Library Benchmark Example with Gungraun Source: https://gungraun.github.io/gungraun/latest/html/cli_and_env/output/terminal_output This Rust code demonstrates how to define and run a library benchmark using the Gungraun framework. It includes setup functions, a benchmark function that prints to stdout, and a teardown function that prints to stderr. The `black_box` function is used to prevent optimizations from affecting the benchmark. This example is intended to be run with Gungraun's benchmarking capabilities. ```rust extern crate gungraun; use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; fn print_to_stderr(value: u64) { eprintln!("Error output during teardown: {value}"); } fn add_10_and_print(value: u64) -> u64 { let value = value + 10; println!("Output to stdout: {value}"); value } #[library_benchmark] #[bench::some_id(args = (10), teardown = print_to_stderr)] fn bench_library(value: u64) -> u64 { black_box(add_10_and_print(value)) } library_benchmark_group!(name = my_group; benchmarks = bench_library); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Define Multiple Benchmarks with `#[benches]` Source: https://gungraun.github.io/gungraun/latest/html/print This example demonstrates the use of the `#[benches]` attribute to define multiple benchmark cases simultaneously. It shows how to provide arrays of arguments and use a `setup` function for multiple benchmarks within a single attribute. ```rust extern crate gungraun; mod my_lib { pub fn bubble_sort(value: Vec) -> Vec { value } } use gungraun::{library_benchmark, library_benchmark_group, main, LibraryBenchmarkConfig}; use std::hint::black_box; pub fn worst_case(start: i32) -> Vec { if start.is_negative() { (start..0).rev().collect() } else { (0..start).rev().collect() } } #[library_benchmark] #[benches::worst_two_and_three(args = [vec![2, 1], vec![3, 2, 1]])] #[benches::worst_four_to_nine(args = [4, 5, 6, 7, 8, 9], setup = worst_case)] fn bench_bubble_sort(value: Vec) -> Vec { black_box(my_lib::bubble_sort(value)) } library_benchmark_group!(name = bubble_sort_group; benchmarks = bench_bubble_sort); fn main() { main!(library_benchmark_groups = bubble_sort_group); } ``` -------------------------------- ### Control Callgrind Instrumentation Entry Point in Rust Source: https://gungraun.github.io/gungraun/latest/html/print Demonstrates setting a custom entry point for Callgrind instrumentation in Gungraun benchmarks. By default, the benchmark function itself serves as the entry point. This example shows how to explicitly define a benchmark function and control when instrumentation starts and stops, useful for excluding setup or teardown code from measurements. ```rust // <-- collect-at-start=no extern crate gungraun; mod my_lib { pub fn bubble_sort(_: Vec) -> Vec { vec![] } } use gungraun::{main,library_benchmark_group, library_benchmark}; use std::hint::black_box; #[library_benchmark] fn bench() -> Vec { // <-- DEFAULT ENTRY POINT starts collecting events black_box(my_lib::bubble_sort(vec![3, 2, 1])) } // <-- stop collecting events library_benchmark_group!( name = my_group; benchmarks = bench); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Running Gungraun Benchmarks Source: https://gungraun.github.io/gungraun/latest/html/print This command initiates the benchmarking process defined in the project. After setup, running this command will execute the benchmarks and display their performance metrics. ```bash __ cargo bench ``` -------------------------------- ### Stdin Setup with Pipe for Binary Benchmark Source: https://gungraun.github.io/gungraun/latest/html/print Shows how to use the `Stdin::Setup` variant in Gungraun to pipe the output of a setup function to the benchmarked command's stdin. This is useful for benchmarking scenarios where input is provided via pipes, like `echo "content" | my-foo`. The `setup` function's stdout becomes the command's stdin. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main, Stdin, Pipe}; fn setup_pipe() { println!( "The output to `Stdout` here will be the input or `Stdin` of the `Command`" ); } #[binary_benchmark] #[bench::foo(setup = setup_pipe())] // Setup is called directly here fn bench_binary() -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .stdin(Stdin::Setup(Pipe::Stdout)) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Benchmark with Setup and Teardown Source: https://gungraun.github.io/gungraun/latest/html/print This Rust code defines a benchmark function that utilizes setup and teardown logic. The setup involves copying a fixture, and the teardown copies a file back. It demonstrates dependency on external files and potential failure if prerequisites are not met. ```rust fn copy_back(path: &str) { let workspace_root = PathBuf::from(std::env::var_os("_WORKSPACE_ROOT").unwrap()); let dest_dir = workspace_root.join("foo_crate").join("tmp"); if !dest_dir.exists() { std::fs::create_dir(&dest_dir).unwrap(); } std::fs::copy(path, dest_dir.join(path)); } #[binary_benchmark] #[bench::foo( args = ("foo.txt"), config = BinaryBenchmarkConfig::default().sandbox(Sandbox::new(true)), setup = copy_fixture, teardown = copy_back("bar.json") )] fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### File Input Benchmark with Setup Function (Rust) Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/multiple_benches Illustrates using the `file` parameter along with a `setup` function to process lines from a file before passing them to the benchmark function. This is useful for parsing and transforming input data, such as CSV-like formats, into the required types for the benchmark. ```rust extern crate gungraun; mod my_lib { pub fn rgb_to_hsv(a: u8, b: u8, c:u8) -> (u16, u8, u8) { (a.into(), b, c) } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; fn decode_line(line: String) -> (u8, u8, u8) { if let &[a, b, c] = line.split(";") .map(|s| s.parse::().unwrap()) .collect::>() .as_slice() { (a, b, c) } else { panic!("Wrong input format in line '{line}'"); } } #[library_benchmark] #[benches::from_file(file = "benches/inputs", setup = decode_line)] fn some_bench((a, b, c): (u8, u8, u8)) -> (u16, u8, u8) { black_box(my_lib::rgb_to_hsv(black_box(a), black_box(b), black_box(c))) } library_benchmark_group!(name = my_group; benchmarks = some_bench); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Advanced `#[bench]` Usage with Setup and Arguments Source: https://gungraun.github.io/gungraun/latest/html/print This snippet illustrates advanced usage of the `#[bench]` attribute, including defining custom argument lists, using a `setup` function to prepare data for the benchmark, and handling different argument types. ```rust // This function is used to create a worst case array we want to sort with our implementation of // bubble sort pub fn worst_case(start: i32) -> Vec { if start.is_negative() { (start..0).rev().collect() } else { (0..start).rev().collect() } } #[library_benchmark] #[bench::one(vec![1])] #[bench::worst_two(args = (vec![2, 1]))] #[bench::worst_four(args = (4), setup = worst_case)] fn bench_bubble_sort(value: Vec) -> Vec { black_box(my_lib::bubble_sort(value)) } library_benchmark_group!(name = bubble_sort_group; benchmarks = bench_bubble_sort); fn main() { main!(library_benchmark_groups = bubble_sort_group); } ``` -------------------------------- ### Rust Low-Level Binary Benchmark Setup Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/quickstart Illustrates the low-level API for benchmarking a binary executable. This approach provides more granular control by directly constructing `BinaryBenchmark` and `Bench` objects within a closure passed to `binary_benchmark_group!`. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{BinaryBenchmark, Bench, binary_benchmark_group, main}; binary_benchmark_group!( name = my_group; benchmarks = |group: &mut BinaryBenchmarkGroup| { group.binary_benchmark(BinaryBenchmark::new("bench_binary") .bench(Bench::new("some_id") .command(gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg("foo.txt") .build() ) ) ) } ); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Advanced Gungraun Benchmark Parameters Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/macros Illustrates advanced usage of Gungraun's `#[bench]` attribute, including custom arguments (`args`), setup functions (`setup`), and defining specific test cases like worst-case scenarios for sorting algorithms. ```rust extern crate gungraun; mod my_lib { pub fn bubble_sort(value: Vec) -> Vec { value } } use gungraun::{library_benchmark, library_benchmark_group, main, LibraryBenchmarkConfig}; use std::hint::black_box; // This function is used to create a worst case array we want to sort with our implementation of // bubble sort pub fn worst_case(start: i32) -> Vec { if start.is_negative() { (start..0).rev().collect() } else { (0..start).rev().collect() } } #[library_benchmark] #[bench::one(vec![1])] #[bench::worst_two(args = (vec![2, 1]))] #[bench::worst_four(args = (4), setup = worst_case)] fn bench_bubble_sort(value: Vec) -> Vec { black_box(my_lib::bubble_sort(value)) } library_benchmark_group!(name = bubble_sort_group; benchmarks = bench_bubble_sort); fn main() { main!(library_benchmark_groups = bubble_sort_group); } ``` -------------------------------- ### Rust Benchmark with Setup and Teardown Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/setup_and_teardown This Rust code defines a benchmark using the Gungraun library. It includes a `setup` function (`open_file`) to prepare resources and a `teardown` function (`print_bytes_read`) to process results after the benchmark. The `black_box` function is used to prevent the compiler from optimizing away the benchmarked code. The `library_benchmark_group!` macro organizes benchmarks, and `main!` macro sets up the entry point for running the benchmarks. ```rust extern crate gungraun; mod my_lib { pub fn count_bytes_fast(_file: std::fs::File) -> u64 { 1 } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; use std::path::PathBuf; use std::fs::File; fn open_file(path: &str) -> File { File::open(path).unwrap() } fn print_bytes_read(num_bytes: u64) { println!("bytes read: {num_bytes}"); } #[library_benchmark] #[bench::first( args = ("path/to/big"), setup = open_file, teardown = print_bytes_read )] fn count_bytes_fast(file: File) -> u64 { black_box(my_lib::count_bytes_fast(file)) } library_benchmark_group!(name = my_group; benchmarks = count_bytes_fast); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Gungraun: Benchmark from File with Setup Function Source: https://gungraun.github.io/gungraun/latest/html/print This snippet demonstrates advanced file input processing using `#[benches::from_file]` with a `setup` function. The `decode_line` function parses CSV-formatted lines from the input file into tuples before they are passed to the benchmark function. ```rust extern crate gungraun; mod my_lib { pub fn rgb_to_hsv(a: u8, b: u8, c:u8) -> (u16, u8, u8) { (a.into(), b, c) } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; fn decode_line(line: String) -> (u8, u8, u8) { if let &[a, b, c] = line.split(";") .map(|s| s.parse::().unwrap()) .collect::>() .as_slice() { (a, b, c) } else { panic!("Wrong input format in line '{line}'"); } } #[library_benchmark] #[benches::from_file(file = "benches/inputs", setup = decode_line)] fn some_bench((a, b, c): (u8, u8, u8)) -> (u16, u8, u8) { black_box(my_lib::rgb_to_hsv(black_box(a), black_box(b), black_box(c))) } library_benchmark_group!(name = my_group; benchmarks = some_bench); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Rust 'cat' Binary Example Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/threads_and_subprocesses A basic Rust program that mimics the 'cat' command. It takes a file path as an argument, reads the file's content, and prints it to standard output. This serves as a simple example of a binary that can be executed by subprocesses. ```rust use std::fs::File; use std::io::{copy, stdout, BufReader, BufWriter, Write}; fn main() { let mut args_iter = std::env::args().skip(1); let file_arg = args_iter.next().expect("File argument should be present"); let file = File::open(file_arg).expect("Opening file should succeed"); let stdout = stdout().lock(); let mut writer = BufWriter::new(stdout); copy(&mut BufReader::new(file), &mut writer) .expect("Printing file to stdout should succeed"); writer.flush().expect("Flushing writer should succeed"); } ``` -------------------------------- ### Equivalent Benchmark using Arguments (Rust) Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/multiple_benches Shows the equivalent benchmark setup using the `from_args` attribute, explicitly listing input arguments instead of reading them from a file. This serves as a comparison to the `from_file` approach, highlighting the convenience of file-based inputs for larger datasets. ```rust extern crate gungraun; mod my_lib { pub fn string_to_u64(value: String) -> Result { Ok(1) } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; #[library_benchmark] #[benches::from_args(args = [1.to_string(), 11.to_string(), 111.to_string()])] fn some_bench(line: String) -> Result { black_box(my_lib::string_to_u64(line)) } library_benchmark_group!(name = my_group; benchmarks = some_bench); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Binary Benchmark Configuration and Execution Source: https://gungraun.github.io/gungraun/latest/html/print Demonstrates how to set up and run binary benchmarks using gungraun. It includes configuring stdout redirection based on file extensions and setting up benchmark groups and the main entry point. This example utilizes Rust macros like `#[binary_benchmark]`, `#[bench]`, `binary_benchmark_group!`, and `main!`. ```rust __ extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main}; use std::path::PathBuf; #[binary_benchmark] #[bench::foo("foo.txt")] #[bench::bar("bar.json")] fn bench_binary(path: &str) -> gungraun::Command { // We can put any code in this function which is needed to configure and // build the `Command`. let path = PathBuf::from(path); // Here, if the `path` ends with `.txt` we want to see // the `Stdout` output of the `Command` in the benchmark output. In all other // cases, the `Stdout` of the `Command` is redirected to a `File` with the // same name as the input `path` but with the extension `out`. let stdout = if path.extension().unwrap() == "txt" { gungraun::Stdio::Inherit } else { gungraun::Stdio::File(path.with_extension("out")) }; gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .stdout(stdout) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Benchmark Setup with gungraun Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/threads_and_subprocesses Sets up and runs benchmark groups using the gungraun library. This involves defining benchmark groups and then invoking the main benchmark runner. It requires the `gungraun` crate and potentially other benchmarking utilities. ```rust library_benchmark_group!(name = my_group; benchmarks = bench_threads); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Enable Debug Symbols for Cargo Benchmarks Source: https://gungraun.github.io/gungraun/latest/html/installation/prerequisites This configuration ensures that debug symbols are included when running benchmarks with `cargo bench`. This is crucial for tools like Gungraun that may rely on detailed debugging information. Ensure that stripping of debug symbols is disabled for the 'bench' profile if it's enabled for the 'release' profile. ```toml [profile.bench] debug = true ``` ```toml [profile.release] strip = true [profile.bench] debug = true strip = false ``` -------------------------------- ### Benchmark with Setup Function for PathBuf Conversion Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/generic This Rust code shows the recommended approach for generic benchmarks using Gungraun. It utilizes a separate setup function ('convert_to_pathbuf') to handle the conversion of string literals to PathBuf. This ensures that the conversion overhead is not included in the benchmark's measured time, providing more accurate performance results. It uses the 'gungraun' crate for benchmarking. ```rust extern crate gungraun; mod my_lib { pub fn count_lines_in_file_fast(_path: std::path::PathBuf) -> u64 { 1 } } use gungraun::{library_benchmark, library_benchmark_group, main}; use std::hint::black_box; use std::path::PathBuf; fn convert_to_pathbuf(path: T) -> PathBuf where T: Into { path.into() } #[library_benchmark] #[bench::first(args = ("path/to/file"), setup = convert_to_pathbuf)] fn not_generic_anymore(path: PathBuf) -> u64 { black_box(my_lib::count_lines_in_file_fast(path)) } library_benchmark_group!(name = my_group; benchmarks = not_generic_anymore); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Benchmark Output Analysis Source: https://gungraun.github.io/gungraun/latest/html/print This example shows the typical output from a Rust benchmark run using gungraun. It details performance metrics for different threads, including instructions, cache hits, and estimated cycles. ```text __ lib_bench_threads::my_group::bench_threads two_threads:**2** ## **pid: 2251257 thread: 1 part: 1** |N/A Command: **target/release/deps/lib_bench_threads-b85159a94ccb3851** Instructions: **0**|N/A (*********) L1 Hits: **0**|N/A (*********) LL Hits: **0**|N/A (*********) RAM Hits: **0**|N/A (*********) Total read+write: **0**|N/A (*********) Estimated Cycles: **0**|N/A (*********) ## **pid: 2251257 thread: 2 part: 1** |N/A Command: **target/release/deps/lib_bench_threads-b85159a94ccb3851** Instructions: **2460501**|N/A (*********) L1 Hits: **2534935**|N/A (*********) LL Hits: **11**|N/A (*********) RAM Hits: **187**|N/A (*********) Total read+write: **2535133**|N/A (*********) Estimated Cycles: **2541535**|N/A (*********) ## **pid: 2251257 thread: 3 part: 1** |N/A Command: **target/release/deps/lib_bench_threads-b85159a94ccb3851** Instructions: **3650408**|N/A (*********) L1 Hits: **3724282**|N/A (*********) LL Hits: **4**|N/A (*********) RAM Hits: **131**|N/A (*********) Total read+write: **3724417**|N/A (*********) Estimated Cycles: **3728887**|N/A (*********) ## **Total** Instructions: **6110909**|N/A (*********) L1 Hits: **6259217**|N/A (*********) LL Hits: **15**|N/A (*********) RAM Hits: **318**|N/A (*********) Total read+write: **6259550**|N/A (*********) Estimated Cycles: **6270422**|N/A (*********) Gungraun result: **Ok**. 1 without regressions; 0 regressed; 0 filtered; 1 benchmarks finished in 0.49333s ``` -------------------------------- ### Rust: Benchmark with Sandbox and Setup Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/configuration/sandbox This snippet demonstrates how to use the Gungraun Sandbox with a setup function to create a file before executing a benchmark command. The Sandbox ensures the file exists during the benchmark and is automatically cleaned up afterward. Dependencies include the 'gungraun' crate. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{ binary_benchmark, binary_benchmark_group, main, BinaryBenchmarkConfig, Sandbox }; fn create_file(path: &str) { std::fs::write(path, "some content").unwrap(); } #[binary_benchmark] #[bench::foo( args = ("foo.txt"), config = BinaryBenchmarkConfig::default().sandbox(Sandbox::new(true)), setup = create_file )] fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust: Configure DHAT with Custom Entry Point in Gungraun Source: https://gungraun.github.io/gungraun/latest/html/print This snippet demonstrates how to configure Gungraun's main function to use DHAT with a custom entry point. It specifies the `setup_worst_case_array` function as the entry point for metrics collection, which is useful when setup code modifies data used by the benchmarked function. This ensures accurate measurement of memory accesses within the setup code. ```rust extern crate gungraun; mod my_lib { pub fn bubble_sort(_: Vec) -> Vec { vec![] } } use std::hint::black_box; use gungraun::{ library_benchmark, library_benchmark_group, main, Dhat, EntryPoint, LibraryBenchmarkConfig, }; pub fn setup_worst_case_array(start: i32) -> Vec { if start.is_negative() { (start..0).rev().collect() } else { (0..start).rev().collect() } } #[library_benchmark] #[bench::worst_case_3(setup_worst_case_array(3))] fn bench_library(array: Vec) -> Vec { black_box(my_lib::bubble_sort(array)) } library_benchmark_group!(name = my_group; benchmarks = bench_library); fn main() { main!( config = LibraryBenchmarkConfig::default() .tool(Dhat::default() .entry_point( EntryPoint::Custom("*::setup_worst_case_array".to_owned()) ) ); library_benchmark_groups = my_group ); } ``` -------------------------------- ### Running Gungraun Benchmarks Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/quickstart This command initiates the benchmark process defined in your project using Cargo. It will compile and run the benchmarks, producing detailed performance metrics. ```bash cargo bench ``` -------------------------------- ### Running Gungraun Benchmarks with Output Capture Disabled Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/setup_and_teardown This command demonstrates how to run Gungraun benchmarks while disabling the default output capture. This is necessary to view the output generated by the `setup` and `teardown` functions within the benchmark results. The `GUNGRAUN_NOCAPTURE=true` environment variable or the `--nocapture` flag can be used. ```bash GUNGRAUN_NOCAPTURE=true cargo bench ``` -------------------------------- ### Example Binary main.rs Structure for Benchmarking Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/overview This snippet demonstrates a basic structure of a Rust binary's main.rs file. It defines a module 'my_lib' with a 'run' function and then calls this function from 'main'. This structure is relevant for understanding how library functions can be integrated into binaries and subsequently benchmarked. ```rust mod my_lib { pub fn run() {} } use my_lib::run; fn main() { run(); } ``` -------------------------------- ### Rust Benchmark Setup with Callgrind Thread Metrics Source: https://gungraun.github.io/gungraun/latest/html/print This Rust code demonstrates how to configure a library benchmark using the Gungraun library and Callgrind to collect thread-specific performance metrics. It utilizes `#[library_benchmark]` with `Callgrind` configured to collect data at the start and disable the entry point, enabling detailed analysis of multi-threaded execution. The benchmark targets a function `find_primes_multi_thread` which is expected to perform prime number calculations. ```rust __ extern crate gungraun; mod my_lib { pub fn find_primes_multi_thread(_: usize) -> Vec { vec![] }} use gungraun::{ main, library_benchmark_group, library_benchmark, LibraryBenchmarkConfig, EntryPoint, Callgrind }; use std::hint::black_box; #[library_benchmark( config = LibraryBenchmarkConfig::default() .tool(Callgrind::with_args(["--collect-atstart=yes"]) .entry_point(EntryPoint::None) ) )] #[bench::two_threads(2)] fn bench_threads(num_threads: usize) -> Vec { black_box(my_lib::find_primes_multi_thread(num_threads)) } library_benchmark_group!(name = my_group; benchmarks = bench_threads); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Rust High-Level Binary Benchmark Setup Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/quickstart Demonstrates the high-level API for benchmarking a binary executable. It uses the `#[binary_benchmark]` attribute and `binary_benchmark_group!` macro to define and group benchmarks. The `env!` macro with `CARGO_BIN_EXE_` is used to correctly locate the binary. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main}; #[binary_benchmark] #[bench::some_id("foo.txt")] fn bench_binary(path: &str) -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!( name = my_group; benchmarks = bench_binary ); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Configure Benchmark-Level Library Benchmarks in Rust Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/configuration This Rust example shows how to apply `LibraryBenchmarkConfig` directly to an individual benchmark function marked with `#[library_benchmark]`. This allows for fine-grained configuration of specific benchmarks. ```rust extern crate gungraun; mod my_lib { pub fn bubble_sort(_: Vec) -> Vec { vec![] } } use gungraun::{ main, LibraryBenchmarkConfig, library_benchmark_group, library_benchmark }; use std::hint::black_box; #[library_benchmark(config = LibraryBenchmarkConfig::default())] fn bench() { /* ... */ } library_benchmark_group!( name = my_group; config = LibraryBenchmarkConfig::default(); benchmarks = bench ); fn main() { main!(library_benchmark_groups = my_group); } ``` -------------------------------- ### Configure Benchmark Output Format with `#[library_benchmark]` Source: https://gungraun.github.io/gungraun/latest/html/print This example shows how to configure the output format of benchmarks using `LibraryBenchmarkConfig` within the `#[library_benchmark]` attribute. It specifically demonstrates how to set the `truncate_description` option. ```rust extern crate gungraun; mod my_lib { pub fn bubble_sort(value: Vec) -> Vec { value } } use gungraun::{ library_benchmark, library_benchmark_group, main, LibraryBenchmarkConfig, OutputFormat }; use std::hint::black_box; #[library_benchmark( config = LibraryBenchmarkConfig::default() .output_format(OutputFormat::default() .truncate_description(None) ) )] #[bench::one(vec![1])] fn bench_bubble_sort(values: Vec) -> Vec { black_box(my_lib::bubble_sort(values)) } library_benchmark_group!(name = bubble_sort_group; benchmarks = bench_bubble_sort); fn main() { main!(library_benchmark_groups = bubble_sort_group); } ``` -------------------------------- ### Configure Command Stdin with Setup Pipe in Rust Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/binary_benchmarks/stdin_and_pipe This Rust code demonstrates how to configure the standard input (Stdin) of a Gungraun Command to use the standard output (Stdout) of a setup function as its input. This is useful for benchmarking scenarios where one process's output feeds into another's input. It utilizes Gungraun's `Stdin::Setup` and `Pipe::Stdout` variants. ```rust extern crate gungraun; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use gungraun::{binary_benchmark, binary_benchmark_group, main, Stdin, Pipe}; fn setup_pipe() { println!( "The output to `Stdout` here will be the input or `Stdin` of the `Command`" ); } #[binary_benchmark] #[bench::foo(setup = setup_pipe())] fn bench_binary() -> gungraun::Command { gungraun::Command::new(env!("CARGO_BIN_EXE_my-foo")) .stdin(Stdin::Setup(Pipe::Stdout)) .build() } binary_benchmark_group!(name = my_group; benchmarks = bench_binary); fn main() { main!(binary_benchmark_groups = my_group); } ``` -------------------------------- ### Rust Library Benchmark Example with Gungraun Source: https://gungraun.github.io/gungraun/latest/html/benchmarks/library_benchmarks/quickstart This Rust code demonstrates how to create a library benchmark using Gungraun. It includes a sample fibonacci function, defines benchmark functions using `#[library_benchmark]` and `#[bench::...]`, and groups them using `library_benchmark_group!` for execution via `main!`. ```rust extern crate gungraun; use gungraun::{main, library_benchmark_group, library_benchmark}; use std::hint::black_box; fn fibonacci(n: u64) -> u64 { match n { 0 => 1, 1 => 1, n => fibonacci(n - 1) + fibonacci(n - 2), } } #[library_benchmark] #[bench::short(10)] #[bench::long(30)] fn bench_fibonacci(value: u64) -> u64 { black_box(fibonacci(value)) } library_benchmark_group!( name = bench_fibonacci_group; benchmarks = bench_fibonacci ); fn main() { main!(library_benchmark_groups = bench_fibonacci_group); } ```