Factored out test program and fuzzing features; core crate now only depends on smallvec and log.

This commit is contained in:
Chris Fallin
2021-04-18 13:38:05 -07:00
parent 34ab744f4f
commit 414f3f828d
6 changed files with 39 additions and 15 deletions

28
test/Cargo.toml Normal file
View File

@@ -0,0 +1,28 @@
[package]
name = "regalloc2-test"
version = "0.0.1"
authors = ["Chris Fallin <chris@cfallin.org>", "Mozilla SpiderMonkey Developers"]
edition = "2018"
license = "Apache-2.0 WITH LLVM-exception AND MPL-2.0"
description = "small test driver for benchmarking regalloc2"
repository = "https://github.com/bytecodealliance/regalloc2"
[dependencies]
regalloc2 = { version = "*", path = "../", features = ["fuzzing"] }
# Keep this in sync with libfuzzer_sys's crate version:
arbitrary = { version = "^0.4.6" }
rand = { version = "0.8" }
rand_chacha = { version = "0.3" }
env_logger = { version = "*" }
[dev-dependencies]
criterion = "0.3"
[profile.release]
debug = true
[[bench]]
name = "regalloc"
harness = false

56
test/benches/regalloc.rs Normal file
View File

@@ -0,0 +1,56 @@
//! Criterion-based benchmark target that computes insts/second for
//! arbitrary inputs.
use arbitrary::{Arbitrary, Unstructured};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
use regalloc2::fuzzing::func::{machine_env, Func};
use regalloc2::ion;
use regalloc2::Function;
fn create_random_func(seed: u64, size: usize) -> Func {
let mut bytes: Vec<u8> = vec![];
bytes.resize(size, 0);
let mut rng = ChaCha8Rng::seed_from_u64(seed);
rng.fill(&mut bytes[..]);
loop {
let mut u = Unstructured::new(&bytes[..]);
match Func::arbitrary(&mut u) {
Ok(f) => {
return f;
}
Err(arbitrary::Error::NotEnoughData) => {
let len = bytes.len();
bytes.resize(len + 1024, 0);
rng.fill(&mut bytes[len..]);
}
Err(e) => panic!("unexpected error: {:?}", e),
}
}
}
fn run_regalloc(c: &mut Criterion) {
const SIZE: usize = 1000 * 1000;
env_logger::init();
let env = machine_env();
let mut group = c.benchmark_group("benches");
for iter in 0..3 {
let func = create_random_func(iter, SIZE);
eprintln!("==== {} instructions", func.insts());
group.throughput(Throughput::Elements(func.insts() as u64));
group.bench_with_input(BenchmarkId::from_parameter(iter), &iter, |b, _| {
b.iter(|| {
// For fair comparison with regalloc.rs, which needs
// to clone its Func on every alloc, we clone
// too. Seems to make a few percent difference.
let func = func.clone();
ion::run(&func, &env).expect("regalloc did not succeed");
});
});
}
group.finish();
}
criterion_group!(benches, run_regalloc);
criterion_main!(benches);

50
test/src/main.rs Normal file
View File

@@ -0,0 +1,50 @@
/*
* Released under the terms of the Apache 2.0 license with LLVM
* exception. See `LICENSE` for details.
*/
use arbitrary::{Arbitrary, Unstructured};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
use regalloc2::fuzzing::func::{machine_env, Func};
use regalloc2::ion;
use regalloc2::Function;
fn create_random_func(seed: u64, size: usize) -> Func {
let mut bytes: Vec<u8> = vec![];
bytes.resize(size, 0);
let mut rng = ChaCha8Rng::seed_from_u64(seed);
rng.fill(&mut bytes[..]);
loop {
let mut u = Unstructured::new(&bytes[..]);
match Func::arbitrary(&mut u) {
Ok(f) => {
return f;
}
Err(arbitrary::Error::NotEnoughData) => {
let len = bytes.len();
bytes.resize(len + 1024, 0);
rng.fill(&mut bytes[len..]);
}
Err(e) => panic!("unexpected error: {:?}", e),
}
}
}
fn main() {
const SIZE: usize = 1000 * 1000;
env_logger::init();
let env = machine_env();
for iter in 0..3 {
let func = create_random_func(iter, SIZE);
eprintln!("==== {} instructions", func.insts());
let mut stats: ion::Stats = ion::Stats::default();
for i in 0..1000 {
let out = ion::run(&func, &env).expect("regalloc did not succeed");
if i == 0 {
stats = out.stats;
}
}
eprintln!("Stats: {:?}", stats);
}
}