Skip to content

Commit

Permalink
bench: switch to criterion
Browse files Browse the repository at this point in the history
Switches the benchmark framework to Criterion. The default Rust std test
framework has a hardcoded goal execution time of 1ms for each benchmark.
This makes it unsuitable for sample-based profiling because the
benchmark doesn't run for very long.

Adds a utility script to run tests under a profiler.
  • Loading branch information
jcdickinson committed Nov 17, 2024
1 parent 8c52723 commit 60d4782
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 51 deletions.
4 changes: 4 additions & 0 deletions benches/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
target
perf.data
perf.data.old
Cargo.lock
7 changes: 7 additions & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ edition = "2018"
harfbuzz_rs = { git = "https://github.com/harfbuzz/harfbuzz_rs/", rev = "43f0fb5" }
rustybuzz = { path = "../" }

[dev-dependencies]
criterion = "0.3"
criterion-macro = "0.3"

[features]
default = ["hb"]
hb = []

[profile.bench]
debug = 2
15 changes: 15 additions & 0 deletions benches/measure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -euo pipefail

export HARFBUZZ_SYS_NO_PKG_CONFIG=""

# Using jq here would be best, however it's not installed by default on many systems, and this isn't a critical script.
TEST_EXECUTABLE=$(
cargo +nightly bench \
--message-format=json \
--no-default-features --no-run | \
grep '^{"reason":"compiler-artifact"' | \
sed -n 's/^.*"executable":"\([^"]*\)".*$/\1/p'
)

exec perf record --call-graph dwarf -- "$TEST_EXECUTABLE" --bench --profile-time 5 "$@"
105 changes: 54 additions & 51 deletions benches/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#![feature(test)]
#![allow(dead_code)]
#![allow(unused_imports)]
#![feature(custom_test_frameworks)]
#![test_runner(criterion::runner)]

extern crate test;

use criterion::{black_box, Criterion};
use criterion_macro::criterion;
use rustybuzz::ttf_parser::Tag;

struct CustomVariation {
Expand All @@ -29,34 +33,34 @@ macro_rules! simple_bench {
use super::*;
use test::Bencher;

#[bench]
fn rb(bencher: &mut Bencher) {
#[criterion]
fn rb(c: &mut Criterion) {
let font_data = std::fs::read($font_path).unwrap();
let text = std::fs::read_to_string($text_path).unwrap().trim().to_string();
bencher.iter(|| {
test::black_box({
let face = rustybuzz::Face::from_slice(&font_data, 0).unwrap();
let mut buffer = rustybuzz::UnicodeBuffer::new();
buffer.push_str(&text);
buffer.reset_clusters();
rustybuzz::shape(&face, &[], buffer);
});
})
}

#[cfg(feature = "hb")]
#[bench]
fn hb(bencher: &mut Bencher) {
let font_data = std::fs::read($font_path).unwrap();
let text = std::fs::read_to_string($text_path).unwrap().trim().to_string();
bencher.iter(|| {
test::black_box({
let face = harfbuzz_rs::Face::from_bytes(&font_data, 0);
let font = harfbuzz_rs::Font::new(face);
c.bench_function(&format!("{}::{}", module_path!(), "rb"), |bencher| {
let face = rustybuzz::Face::from_slice(&font_data, 0).unwrap();

bencher.iter(|| {
black_box({
let mut buffer = rustybuzz::UnicodeBuffer::new();
buffer.push_str(&text);
buffer.reset_clusters();
rustybuzz::shape(&face, &[], buffer);
});
})
});

#[cfg(feature = "hb")]
c.bench_function(&format!("{}::{}", module_path!(), "hb"), |bencher| {
let face = harfbuzz_rs::Face::from_bytes(&font_data, 0);
let font = harfbuzz_rs::Font::new(face);

bencher.iter(|| {
let buffer = harfbuzz_rs::UnicodeBuffer::new().add_str(&text);
harfbuzz_rs::shape(&font, buffer, &[])
});
})
black_box({ harfbuzz_rs::shape(&font, buffer, &[]) });
})
});
}
}
};
Expand All @@ -67,36 +71,35 @@ macro_rules! simple_bench {
use super::*;
use test::Bencher;

#[bench]
fn rb(bencher: &mut Bencher) {
let font_data = std::fs::read($font_path).unwrap();
let text = std::fs::read_to_string($text_path).unwrap().trim().to_string();
bencher.iter(|| {
test::black_box({
let mut face = rustybuzz::Face::from_slice(&font_data, 0).unwrap();
face.set_variations($variations);
let mut buffer = rustybuzz::UnicodeBuffer::new();
buffer.push_str(&text);
buffer.reset_clusters();
rustybuzz::shape(&face, &[], buffer);
});
})
}

#[cfg(feature = "hb")]
#[bench]
fn hb(bencher: &mut Bencher) {
#[criterion]
fn rb(c: &mut Criterion) {
let font_data = std::fs::read($font_path).unwrap();
let text = std::fs::read_to_string($text_path).unwrap().trim().to_string();
bencher.iter(|| {
test::black_box({
let face = harfbuzz_rs::Face::from_bytes(&font_data, 0);
let mut font = harfbuzz_rs::Font::new(face);
font.set_variations($variations);
c.bench_function(&format!("{}::{}", module_path!(), "rb"), |bencher| {
let mut face = rustybuzz::Face::from_slice(&font_data, 0).unwrap();
face.set_variations($variations);

bencher.iter(|| {
black_box({
let mut buffer = rustybuzz::UnicodeBuffer::new();
buffer.push_str(&text);
buffer.reset_clusters();
rustybuzz::shape(&face, &[], buffer);
});
})
});

#[cfg(feature = "hb")]
c.bench_function(&format!("{}::{}", module_path!(), "hb"), |bencher| {
let face = harfbuzz_rs::Face::from_bytes(&font_data, 0);
let mut font = harfbuzz_rs::Font::new(face);
font.set_variations($variations);

bencher.iter(|| {
let buffer = harfbuzz_rs::UnicodeBuffer::new().add_str(&text);
harfbuzz_rs::shape(&font, buffer, &[])
});
})
black_box({ harfbuzz_rs::shape(&font, buffer, &[]) });
})
});
}
}
};
Expand Down

0 comments on commit 60d4782

Please sign in to comment.