Skip to content

Commit cffd0e7

Browse files
committed
Port benchmark to criterion
1 parent 099b0ed commit cffd0e7

File tree

4 files changed

+146
-161
lines changed

4 files changed

+146
-161
lines changed

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,19 @@ rustc-hash = "2.0"
3434
[dev-dependencies]
3535
pyo3 = { version = "0.28.0", default-features = false, features = ["auto-initialize"]}
3636
nalgebra = { version = ">=0.30, <0.35", default-features = false, features = ["std"] }
37+
criterion = "0.8.2"
3738

3839
[build-dependencies]
3940
pyo3-build-config = { version = "0.28", features = ["resolve-config"]}
4041

42+
[[bench]]
43+
name = "array"
44+
harness = false
45+
46+
[[bench]]
47+
name = "borrow"
48+
harness = false
49+
4150
[package.metadata.docs.rs]
4251
all-features = true
4352

benches/array.rs

Lines changed: 108 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
1-
#![feature(test)]
2-
3-
extern crate test;
4-
use test::{black_box, Bencher};
5-
6-
use std::ops::Range;
1+
use std::{hint::black_box, ops::Range};
72

3+
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
84
use numpy::{PyArray1, PyArray2, PyArray3};
95
use pyo3::{types::PyAnyMethods, Bound, IntoPyObjectExt, Python};
106

11-
#[bench]
12-
fn extract_success(bencher: &mut Bencher) {
7+
fn extract_success(c: &mut Criterion) {
138
Python::attach(|py| {
149
let any = PyArray2::<f64>::zeros(py, (10, 10), false).into_any();
1510

16-
bencher.iter(|| {
17-
black_box(&any)
18-
.extract::<Bound<'_, PyArray2<f64>>>()
19-
.unwrap()
11+
c.bench_function("extract_success", |b| {
12+
b.iter(|| {
13+
black_box(&any)
14+
.extract::<Bound<'_, PyArray2<f64>>>()
15+
.unwrap()
16+
});
2017
});
2118
});
2219
}
2320

24-
#[bench]
25-
fn extract_failure(bencher: &mut Bencher) {
21+
fn extract_failure(c: &mut Criterion) {
2622
Python::attach(|py| {
2723
let any = PyArray2::<i32>::zeros(py, (10, 10), false).into_any();
2824

29-
bencher.iter(|| {
30-
black_box(&any)
31-
.extract::<Bound<'_, PyArray2<f64>>>()
32-
.unwrap_err()
25+
c.bench_function("extract_failure", |b| {
26+
b.iter(|| {
27+
black_box(&any)
28+
.extract::<Bound<'_, PyArray2<f64>>>()
29+
.unwrap_err()
30+
});
3331
});
3432
});
3533
}
3634

37-
#[bench]
38-
fn cast_success(bencher: &mut Bencher) {
35+
fn cast_success(c: &mut Criterion) {
3936
Python::attach(|py| {
4037
let any = PyArray2::<f64>::zeros(py, (10, 10), false).into_any();
4138

42-
bencher.iter(|| black_box(&any).cast::<PyArray2<f64>>().unwrap());
39+
c.bench_function("cast_success", |b| {
40+
b.iter(|| black_box(&any).cast::<PyArray2<f64>>().unwrap());
41+
});
4342
});
4443
}
4544

46-
#[bench]
47-
fn cast_failure(bencher: &mut Bencher) {
45+
fn cast_failure(c: &mut Criterion) {
4846
Python::attach(|py| {
4947
let any = PyArray2::<i32>::zeros(py, (10, 10), false).into_any();
5048

51-
bencher.iter(|| black_box(&any).cast::<PyArray2<f64>>().unwrap_err());
49+
c.bench_function("cast_failure", |b| {
50+
b.iter(|| black_box(&any).cast::<PyArray2<f64>>().unwrap_err());
51+
})
5252
});
5353
}
5454

@@ -62,139 +62,111 @@ impl Iterator for Iter {
6262
}
6363
}
6464

65-
fn from_iter(bencher: &mut Bencher, size: usize) {
66-
Python::attach(|py| {
67-
bencher.iter(|| {
68-
let iter = black_box(Iter(0..size));
65+
fn from_iter(c: &mut Criterion) {
66+
const SIZES: &[usize] = &[2_usize.pow(5), 2_usize.pow(10), 2_usize.pow(15)];
6967

70-
PyArray1::from_iter(py, iter)
68+
let mut group = c.benchmark_group("from_iter");
69+
for &size in SIZES {
70+
Python::attach(|py| {
71+
group.throughput(Throughput::Elements(size as u64));
72+
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _size| {
73+
b.iter(|| {
74+
let iter = black_box(Iter(0..size));
75+
black_box(PyArray1::from_iter(py, iter));
76+
});
77+
});
7178
});
72-
});
73-
}
74-
75-
#[bench]
76-
fn from_iter_small(bencher: &mut Bencher) {
77-
from_iter(bencher, 2_usize.pow(5));
78-
}
79-
80-
#[bench]
81-
fn from_iter_medium(bencher: &mut Bencher) {
82-
from_iter(bencher, 2_usize.pow(10));
83-
}
84-
85-
#[bench]
86-
fn from_iter_large(bencher: &mut Bencher) {
87-
from_iter(bencher, 2_usize.pow(15));
79+
}
8880
}
8981

90-
fn from_slice(bencher: &mut Bencher, size: usize) {
91-
let vec = (0..size).collect::<Vec<_>>();
82+
fn from_slice(c: &mut Criterion) {
83+
const SIZES: &[usize] = &[2_usize.pow(5), 2_usize.pow(10), 2_usize.pow(15)];
9284

93-
Python::attach(|py| {
94-
bencher.iter(|| {
95-
let slice = black_box(&vec);
85+
let mut group = c.benchmark_group("from_slice");
86+
for &size in SIZES {
87+
let vec = (0..size).collect::<Vec<_>>();
9688

97-
PyArray1::from_slice(py, slice)
89+
Python::attach(|py| {
90+
group.throughput(Throughput::Elements(size as u64));
91+
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _size| {
92+
b.iter(|| {
93+
let slice = black_box(&vec[..]);
94+
black_box(PyArray1::from_slice(py, slice));
95+
});
96+
});
9897
});
99-
});
100-
}
101-
102-
#[bench]
103-
fn from_slice_small(bencher: &mut Bencher) {
104-
from_slice(bencher, 2_usize.pow(5));
105-
}
106-
107-
#[bench]
108-
fn from_slice_medium(bencher: &mut Bencher) {
109-
from_slice(bencher, 2_usize.pow(10));
110-
}
111-
112-
#[bench]
113-
fn from_slice_large(bencher: &mut Bencher) {
114-
from_slice(bencher, 2_usize.pow(15));
98+
}
11599
}
116100

117-
fn from_object_slice(bencher: &mut Bencher, size: usize) {
118-
let vec = Python::attach(|py| {
119-
(0..size)
120-
.map(|val| val.into_py_any(py).unwrap())
121-
.collect::<Vec<_>>()
122-
});
101+
fn from_object_slice(c: &mut Criterion) {
102+
const SIZES: &[usize] = &[2_usize.pow(5), 2_usize.pow(10), 2_usize.pow(15)];
123103

124-
Python::attach(|py| {
125-
bencher.iter(|| {
126-
let slice = black_box(&vec);
104+
let mut group = c.benchmark_group("from_object_slice");
105+
for &size in SIZES {
106+
Python::attach(|py| {
107+
let vec = (0..size)
108+
.map(|val| val.into_py_any(py).unwrap())
109+
.collect::<Vec<_>>();
127110

128-
PyArray1::from_slice(py, slice)
111+
group.throughput(Throughput::Elements(size as u64));
112+
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _size| {
113+
b.iter(|| {
114+
let slice = black_box(&vec[..]);
115+
black_box(PyArray1::from_slice(py, slice));
116+
});
117+
});
129118
});
130-
});
131-
}
132-
133-
#[bench]
134-
fn from_object_slice_small(bencher: &mut Bencher) {
135-
from_object_slice(bencher, 2_usize.pow(5));
136-
}
137-
138-
#[bench]
139-
fn from_object_slice_medium(bencher: &mut Bencher) {
140-
from_object_slice(bencher, 2_usize.pow(10));
141-
}
142-
143-
#[bench]
144-
fn from_object_slice_large(bencher: &mut Bencher) {
145-
from_object_slice(bencher, 2_usize.pow(15));
119+
}
146120
}
147121

148-
fn from_vec2(bencher: &mut Bencher, size: usize) {
149-
let vec2 = vec![vec![0; size]; size];
122+
fn from_vec2(c: &mut Criterion) {
123+
const SIZES: &[usize] = &[2_usize.pow(3), 2_usize.pow(5), 2_usize.pow(8)];
150124

151-
Python::attach(|py| {
152-
bencher.iter(|| {
153-
let vec2 = black_box(&vec2);
125+
let mut group = c.benchmark_group("from_vec2");
126+
for &size in SIZES {
127+
let vec2 = vec![vec![0; size]; size];
154128

155-
PyArray2::from_vec2(py, vec2).unwrap()
129+
Python::attach(|py| {
130+
group.throughput(Throughput::Elements(size.pow(2) as u64));
131+
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _size| {
132+
b.iter(|| {
133+
let vec2 = black_box(&vec2);
134+
black_box(PyArray2::from_vec2(py, vec2).unwrap());
135+
});
136+
});
156137
});
157-
});
158-
}
159-
160-
#[bench]
161-
fn from_vec2_small(bencher: &mut Bencher) {
162-
from_vec2(bencher, 2_usize.pow(3));
163-
}
164-
165-
#[bench]
166-
fn from_vec2_medium(bencher: &mut Bencher) {
167-
from_vec2(bencher, 2_usize.pow(5));
168-
}
169-
170-
#[bench]
171-
fn from_vec2_large(bencher: &mut Bencher) {
172-
from_vec2(bencher, 2_usize.pow(8));
138+
}
173139
}
174140

175-
fn from_vec3(bencher: &mut Bencher, size: usize) {
176-
let vec3 = vec![vec![vec![0; size]; size]; size];
141+
fn from_vec3(c: &mut Criterion) {
142+
const SIZES: &[usize] = &[2_usize.pow(2), 2_usize.pow(4), 2_usize.pow(5)];
177143

178-
Python::attach(|py| {
179-
bencher.iter(|| {
180-
let vec3 = black_box(&vec3);
144+
let mut group = c.benchmark_group("from_vec3");
145+
for &size in SIZES {
146+
let vec3 = vec![vec![vec![0; size]; size]; size];
181147

182-
PyArray3::from_vec3(py, vec3).unwrap()
148+
Python::attach(|py| {
149+
group.throughput(Throughput::Elements(size.pow(3) as u64));
150+
group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _size| {
151+
b.iter(|| {
152+
let vec3 = black_box(&vec3);
153+
black_box(PyArray3::from_vec3(py, vec3).unwrap());
154+
});
155+
});
183156
});
184-
});
185-
}
186-
187-
#[bench]
188-
fn from_vec3_small(bencher: &mut Bencher) {
189-
from_vec3(bencher, 2_usize.pow(2));
190-
}
191-
192-
#[bench]
193-
fn from_vec3_medium(bencher: &mut Bencher) {
194-
from_vec3(bencher, 2_usize.pow(4));
157+
}
195158
}
196159

197-
#[bench]
198-
fn from_vec3_large(bencher: &mut Bencher) {
199-
from_vec3(bencher, 2_usize.pow(5));
200-
}
160+
criterion_group!(
161+
benches,
162+
extract_success,
163+
extract_failure,
164+
cast_success,
165+
cast_failure,
166+
from_iter,
167+
from_slice,
168+
from_object_slice,
169+
from_vec2,
170+
from_vec3
171+
);
172+
criterion_main!(benches);

benches/borrow.rs

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,57 @@
1-
#![feature(test)]
2-
3-
extern crate test;
4-
use test::{black_box, Bencher};
1+
use std::hint::black_box;
52

3+
use criterion::{criterion_group, criterion_main, Criterion};
64
use numpy::{PyArray, PyArrayMethods};
75
use pyo3::Python;
86

9-
#[bench]
10-
fn initial_shared_borrow(bencher: &mut Bencher) {
7+
fn initial_shared_borrow(c: &mut Criterion) {
118
Python::attach(|py| {
129
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
1310

14-
bencher.iter(|| {
15-
let array = black_box(&array);
11+
c.bench_function("initial_shared_borrow", |bencher| {
12+
bencher.iter(|| {
13+
let array = black_box(&array);
1614

17-
let _shared = array.readonly();
15+
let _shared = black_box(array.readonly());
16+
});
1817
});
1918
});
2019
}
2120

22-
#[bench]
23-
fn additional_shared_borrow(bencher: &mut Bencher) {
21+
fn additional_shared_borrow(c: &mut Criterion) {
2422
Python::attach(|py| {
2523
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
2624

2725
let _shared = (0..128).map(|_| array.readonly()).collect::<Vec<_>>();
2826

29-
bencher.iter(|| {
30-
let array = black_box(&array);
27+
c.bench_function("additional_shared_borrow", |bencher| {
28+
bencher.iter(|| {
29+
let array = black_box(&array);
3130

32-
let _shared = array.readonly();
31+
let _shared = black_box(array.readonly());
32+
});
3333
});
3434
});
3535
}
3636

37-
#[bench]
38-
fn exclusive_borrow(bencher: &mut Bencher) {
37+
fn exclusive_borrow(c: &mut Criterion) {
3938
Python::attach(|py| {
4039
let array = PyArray::<f64, _>::zeros(py, (6, 5, 4, 3, 2, 1), false);
4140

42-
bencher.iter(|| {
43-
let array = black_box(&array);
41+
c.bench_function("exclusive_borrow", |bencher| {
42+
bencher.iter(|| {
43+
let array = black_box(&array);
4444

45-
let _exclusive = array.readwrite();
45+
let _exclusive = black_box(array.readwrite());
46+
});
4647
});
4748
});
4849
}
50+
51+
criterion_group!(
52+
benches,
53+
initial_shared_borrow,
54+
additional_shared_borrow,
55+
exclusive_borrow
56+
);
57+
criterion_main!(benches);

0 commit comments

Comments
 (0)