Skip to content

Commit 7b3063c

Browse files
committed
Add benchmark showing that extract::<i64> is costly due to PyNumber_Index trying hard.
1 parent d71af73 commit 7b3063c

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ harness = false
169169
name = "bench_intern"
170170
harness = false
171171

172+
[[bench]]
173+
name = "bench_extract"
174+
harness = false
175+
172176
[workspace]
173177
members = [
174178
"pyo3-ffi",

benches/bench_extract.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
2+
3+
use pyo3::{
4+
types::{PyDict, PyInt, PyString},
5+
IntoPy, PyAny, PyObject, Python,
6+
};
7+
8+
fn extract_str_extract_success(bench: &mut Bencher<'_>) {
9+
Python::with_gil(|py| {
10+
let s = PyString::new(py, "Hello, World!") as &PyAny;
11+
12+
bench.iter(|| {
13+
let v = black_box(s).extract::<&str>().unwrap();
14+
black_box(v);
15+
});
16+
});
17+
}
18+
19+
fn extract_str_extract_fail(bench: &mut Bencher<'_>) {
20+
Python::with_gil(|py| {
21+
let d = PyDict::new(py) as &PyAny;
22+
23+
bench.iter(|| match black_box(d).extract::<&str>() {
24+
Ok(v) => panic!("should err {}", v),
25+
Err(e) => black_box(e),
26+
});
27+
});
28+
}
29+
30+
fn extract_str_downcast_success(bench: &mut Bencher<'_>) {
31+
Python::with_gil(|py| {
32+
let s = PyString::new(py, "Hello, World!") as &PyAny;
33+
34+
bench.iter(|| {
35+
let py_str = black_box(s).downcast::<PyString>().unwrap();
36+
let v = py_str.to_str().unwrap();
37+
black_box(v);
38+
});
39+
});
40+
}
41+
42+
fn extract_str_downcast_fail(bench: &mut Bencher<'_>) {
43+
Python::with_gil(|py| {
44+
let d = PyDict::new(py) as &PyAny;
45+
46+
bench.iter(|| match black_box(d).downcast::<PyString>() {
47+
Ok(v) => panic!("should err {}", v),
48+
Err(e) => black_box(e),
49+
});
50+
});
51+
}
52+
53+
fn extract_int_extract_success(bench: &mut Bencher<'_>) {
54+
Python::with_gil(|py| {
55+
let int_obj: PyObject = 123.into_py(py);
56+
let int = int_obj.as_ref(py);
57+
58+
bench.iter(|| {
59+
let v = black_box(int).extract::<i64>().unwrap();
60+
black_box(v);
61+
});
62+
});
63+
}
64+
65+
fn extract_int_extract_fail(bench: &mut Bencher<'_>) {
66+
Python::with_gil(|py| {
67+
let d = PyDict::new(py) as &PyAny;
68+
69+
bench.iter(|| match black_box(d).extract::<i64>() {
70+
Ok(v) => panic!("should err {}", v),
71+
Err(e) => black_box(e),
72+
});
73+
});
74+
}
75+
76+
fn extract_int_downcast_success(bench: &mut Bencher<'_>) {
77+
Python::with_gil(|py| {
78+
let int_obj: PyObject = 123.into_py(py);
79+
let int = int_obj.as_ref(py);
80+
81+
bench.iter(|| {
82+
let py_int = black_box(int).downcast::<PyInt>().unwrap();
83+
let v = py_int.extract::<i64>().unwrap();
84+
black_box(v);
85+
});
86+
});
87+
}
88+
89+
fn extract_int_downcast_fail(bench: &mut Bencher<'_>) {
90+
Python::with_gil(|py| {
91+
let d = PyDict::new(py) as &PyAny;
92+
93+
bench.iter(|| match black_box(d).downcast::<PyInt>() {
94+
Ok(v) => panic!("should err {}", v),
95+
Err(e) => black_box(e),
96+
});
97+
});
98+
}
99+
100+
fn criterion_benchmark(c: &mut Criterion) {
101+
c.bench_function("extract_str_extract_success", extract_str_extract_success);
102+
c.bench_function("extract_str_extract_fail", extract_str_extract_fail);
103+
c.bench_function("extract_str_downcast_success", extract_str_downcast_success);
104+
c.bench_function("extract_str_downcast_fail", extract_str_downcast_fail);
105+
c.bench_function("extract_int_extract_success", extract_int_extract_success);
106+
c.bench_function("extract_int_extract_fail", extract_int_extract_fail);
107+
c.bench_function("extract_int_downcast_success", extract_int_downcast_success);
108+
c.bench_function("extract_int_downcast_fail", extract_int_downcast_fail);
109+
}
110+
111+
criterion_group!(benches, criterion_benchmark);
112+
criterion_main!(benches);

0 commit comments

Comments
 (0)