print walltime benchmarks with subnanosecond precision

example results when benchmarking 1-4 serialized ADD instructions

```
running 4 tests
test add  ... bench:           0.24 ns/iter (+/- 0.00)
test add2 ... bench:           0.48 ns/iter (+/- 0.01)
test add3 ... bench:           0.72 ns/iter (+/- 0.01)
test add4 ... bench:           0.96 ns/iter (+/- 0.01)
```
This commit is contained in:
The 8472 2024-05-05 22:38:39 +02:00
parent 872a85658d
commit 295432b40e
2 changed files with 14 additions and 11 deletions

View File

@ -68,12 +68,12 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
use std::fmt::Write; use std::fmt::Write;
let mut output = String::new(); let mut output = String::new();
let median = bs.ns_iter_summ.median as usize; let median = bs.ns_iter_summ.median;
let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize; let deviation = bs.ns_iter_summ.max - bs.ns_iter_summ.min;
write!( write!(
output, output,
"{:>11} ns/iter (+/- {})", "{:>14} ns/iter (+/- {})",
fmt_thousands_sep(median, ','), fmt_thousands_sep(median, ','),
fmt_thousands_sep(deviation, ',') fmt_thousands_sep(deviation, ',')
) )
@ -85,24 +85,27 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
} }
// Format a number with thousands separators // Format a number with thousands separators
fn fmt_thousands_sep(mut n: usize, sep: char) -> String { fn fmt_thousands_sep(mut n: f64, sep: char) -> String {
use std::fmt::Write; use std::fmt::Write;
let mut output = String::new(); let mut output = String::new();
let mut trailing = false; let mut trailing = false;
for &pow in &[9, 6, 3, 0] { for &pow in &[9, 6, 3, 0] {
let base = 10_usize.pow(pow); let base = 10_usize.pow(pow);
if pow == 0 || trailing || n / base != 0 { if pow == 0 || trailing || n / base as f64 >= 1.0 {
if !trailing { match (pow, trailing) {
write!(output, "{}", n / base).unwrap(); // modern CPUs can execute multiple instructions per nanosecond
} else { // e.g. benching an ADD takes about 0.25ns.
write!(output, "{:03}", n / base).unwrap(); (0, true) => write!(output, "{:06.2}", n / base as f64).unwrap(),
(0, false) => write!(output, "{:.2}", n / base as f64).unwrap(),
(_, true) => write!(output, "{:03}", n as usize / base).unwrap(),
_ => write!(output, "{}", n as usize / base).unwrap()
} }
if pow != 0 { if pow != 0 {
output.push(sep); output.push(sep);
} }
trailing = true; trailing = true;
} }
n %= base; n %= base as f64;
} }
output output

View File

@ -2,7 +2,7 @@
# needs-unwind because #[bench] and -Cpanic=abort requires -Zpanic-abort-tests # needs-unwind because #[bench] and -Cpanic=abort requires -Zpanic-abort-tests
include ../tools.mk include ../tools.mk
NORMALIZE=sed 's%[0-9,]\{1,\} ns/iter (+/- [0-9,]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%' NORMALIZE=sed 's%[0-9,\.]\{1,\} ns/iter (+/- [0-9,\.]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%'
all: all:
$(RUSTC) --test tests.rs $(RUSTC) --test tests.rs