-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a benchmark to be run on main branch CI
Also, add the test video asset using git lfs, so that it is relatively easily accessible, but doesn't pollute the repository itself.
- Loading branch information
Showing
7 changed files
with
168 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
big_buck_bunny_1080p_24fps_h264.h264 filter=lfs diff=lfs merge=lfs -text |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: Benchmark | ||
on: | ||
push: | ||
branches: master | ||
jobs: | ||
benchmark_with_bencher: | ||
name: Benchmark with Bencher | ||
runs-on: ubuntu-22.04 | ||
env: | ||
BENCHER_PROJECT: h264-reader | ||
BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }} | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
lfs: true | ||
|
||
- name: Install toolchain | ||
uses: dtolnay/[email protected] | ||
|
||
- uses: bencherdev/bencher@main | ||
- uses: cargo-bins/cargo-binstall@main | ||
|
||
- run: sudo apt-get install valgrind | ||
- run: cargo binstall --no-confirm [email protected] | ||
- run: | | ||
IAI_CALLGRIND_COLOR=never cargo bench --bench ci_bench > perf.txt | ||
- run: | | ||
bencher run \ | ||
--branch "$GITHUB_REF_NAME" \ | ||
--err \ | ||
--adapter rust_iai_callgrind \ | ||
--hash "$GITHUB_SHA" \ | ||
--file "perf.txt" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Benchmarks | ||
|
||
There are two benchmarks here, | ||
|
||
- `bench.rs` | ||
- [criterion.rs](https://github.com/bheisler/criterion.rs) based benchmark suite that measures throughput of various | ||
h264 parsing setups, reporting on parser throughput (i.e. number of megabytes of h264 data parsed per second). | ||
- Provides a view of how fast the parser is on the system on which the benchmark is executed. | ||
- Run using `cargo criterion --bench bench` | ||
- `bench-ci.rs` | ||
- [iai-callgrind](https://github.com/iai-callgrind/iai-callgrind) based benchmark that counts the number of | ||
instructions executed while parsing a test asset | ||
- Provides an indication of performance that is stable even if run on CPUs of varying speeds, or in the face of | ||
CPU contention from other processes (e.g. in a noisy CI environment like github actions). | ||
- Useful for comparing changes in performance over time, not useful for indicating _absolute_ performance. | ||
- run using `cargo bench --bench ci_bench` | ||
|
||
The latter benchmark is run from a github actions workflow on commits to the main branch and the benchmark results are | ||
uploaded to [bencher.dev](https://bencher.dev/perf/h264-reader). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use h264_reader::annexb::AnnexBReader; | ||
use h264_reader::nal::pps::PicParameterSet; | ||
use h264_reader::nal::sei::buffering_period::BufferingPeriod; | ||
use h264_reader::nal::sei::pic_timing::PicTiming; | ||
use h264_reader::nal::sei::user_data_registered_itu_t_t35::ItuTT35; | ||
use h264_reader::nal::sei::HeaderType; | ||
use h264_reader::nal::slice::SliceHeader; | ||
use h264_reader::nal::sps::SeqParameterSet; | ||
use h264_reader::nal::Nal; | ||
use h264_reader::nal::{sei, RefNal, UnitType}; | ||
use h264_reader::push::NalInterest; | ||
use h264_reader::Context; | ||
use iai_callgrind::{library_benchmark, library_benchmark_group, main}; | ||
use std::fs::File; | ||
use std::hint::black_box; | ||
use std::io::Read; | ||
|
||
fn setup_video(filename: &str) -> Vec<u8> { | ||
let mut f = File::open(filename).expect("Test file missing."); | ||
let l = f.metadata().unwrap().len() as usize; | ||
let size = l.min(10 * 1024 * 1024); | ||
let mut buf = vec![0; size]; | ||
f.read_exact(&mut buf[..]).unwrap(); | ||
buf | ||
} | ||
|
||
#[library_benchmark] | ||
#[bench::read(setup_video("big_buck_bunny_1080p_24fps_h264.h264"))] | ||
fn reader(buf: Vec<u8>) { | ||
let mut ctx = Context::new(); | ||
|
||
let mut reader = AnnexBReader::accumulate(|nal: RefNal<'_>| { | ||
if !nal.is_complete() { | ||
return NalInterest::Buffer; | ||
} | ||
|
||
let nal_header = nal.header().unwrap(); | ||
let nal_unit_type = nal_header.nal_unit_type(); | ||
|
||
match nal_unit_type { | ||
UnitType::SeqParameterSet => { | ||
let data = SeqParameterSet::from_bits(nal.rbsp_bits()).unwrap(); | ||
ctx.put_seq_param_set(data); | ||
} | ||
UnitType::PicParameterSet => { | ||
let data = PicParameterSet::from_bits(&ctx, nal.rbsp_bits()).unwrap(); | ||
ctx.put_pic_param_set(data); | ||
} | ||
UnitType::SliceLayerWithoutPartitioningIdr | ||
| UnitType::SliceLayerWithoutPartitioningNonIdr => { | ||
let mut bits = nal.rbsp_bits(); | ||
let (header, _seq_params, _pic_params) = | ||
SliceHeader::from_bits(&ctx, &mut bits, nal_header).unwrap(); | ||
let _ = black_box(header); | ||
} | ||
UnitType::SEI => { | ||
let mut scratch = vec![]; | ||
let mut reader = sei::SeiReader::from_rbsp_bytes(nal.rbsp_bytes(), &mut scratch); | ||
loop { | ||
match reader.next() { | ||
Ok(Some(sei)) => match sei.payload_type { | ||
HeaderType::BufferingPeriod => { | ||
let bp = BufferingPeriod::read(&ctx, &sei); | ||
let _ = black_box(bp); | ||
} | ||
HeaderType::PicTiming => { | ||
let pt = | ||
PicTiming::read(ctx.sps().next().expect("first sps"), &sei); | ||
let _ = black_box(pt); | ||
} | ||
HeaderType::UserDataRegisteredItuTT35 => match ItuTT35::read(&sei) { | ||
Ok(ud) => { | ||
let _ = black_box(ud); | ||
} | ||
Err(e) => { | ||
println!("{:?}", e); | ||
} | ||
}, | ||
_ => {} | ||
}, | ||
Ok(None) => break, | ||
Err(e) => { | ||
println!("{:?}", e); | ||
} | ||
} | ||
} | ||
} | ||
_ => { | ||
println!("Unhandled: {:?}", nal_unit_type); | ||
} | ||
} | ||
NalInterest::Ignore | ||
}); | ||
|
||
reader.push(&buf); | ||
} | ||
|
||
library_benchmark_group!( | ||
name = ci; | ||
benchmarks = reader | ||
); | ||
|
||
main!(library_benchmark_groups = ci); |
Git LFS file not shown