Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pyo3-benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ publish = false
[dependencies]
pyo3 = { path = "../", features = ["auto-initialize", "full"] }

[build-dependencies]
pyo3-build-config = { path = "../pyo3-build-config" }

[dev-dependencies]
codspeed-criterion-compat = "2.3"
criterion = "0.5.1"
num-bigint = "0.4.3"
rust_decimal = { version = "1.0.0", default-features = false }
hashbrown = "0.14"

[[bench]]
name = "bench_any"
Expand Down
4 changes: 2 additions & 2 deletions pyo3-benches/benches/bench_any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn find_object_type(obj: &Bound<'_, PyAny>) -> ObjectType {

fn bench_identify_object_type(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let obj = py.eval_bound("object()", None, None).unwrap();
let obj = py.eval(c"object()", None, None).unwrap();

b.iter(|| find_object_type(&obj));

Expand All @@ -73,7 +73,7 @@ fn bench_identify_object_type(b: &mut Bencher<'_>) {

fn bench_collect_generic_iterator(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let collection = py.eval_bound("list(range(1 << 20))", None, None).unwrap();
let collection = py.eval(c"list(range(1 << 20))", None, None).unwrap();

b.iter(|| {
collection
Expand Down
10 changes: 5 additions & 5 deletions pyo3-benches/benches/bench_bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,39 @@ fn extract_bigint_extract_fail(bench: &mut Bencher<'_>) {

fn extract_bigint_small(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let int = py.eval_bound("-42", None, None).unwrap();
let int = py.eval(c"-42", None, None).unwrap();

bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());
});
}

fn extract_bigint_big_negative(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let int = py.eval_bound("-10**300", None, None).unwrap();
let int = py.eval(c"-10**300", None, None).unwrap();

bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());
});
}

fn extract_bigint_big_positive(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let int = py.eval_bound("10**300", None, None).unwrap();
let int = py.eval(c"10**300", None, None).unwrap();

bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());
});
}

fn extract_bigint_huge_negative(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let int = py.eval_bound("-10**3000", None, None).unwrap();
let int = py.eval(c"-10**3000", None, None).unwrap();

bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());
});
}

fn extract_bigint_huge_positive(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let int = py.eval_bound("10**3000", None, None).unwrap();
let int = py.eval(c"10**3000", None, None).unwrap();

bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());
});
Expand Down
4 changes: 2 additions & 2 deletions pyo3-benches/benches/bench_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn bench_call(b: &mut Bencher<'_>) {
<_ as IntoPy<PyObject>>::into_py("s", py).into_bound(py),
<_ as IntoPy<PyObject>>::into_py(1.23, py).into_bound(py),
);
let kwargs = [("d", 1), ("e", 42)].into_py_dict(py);
let kwargs = [("d", 1), ("e", 42)].into_py_dict(py).unwrap();

b.iter(|| {
for _ in 0..1000 {
Expand Down Expand Up @@ -149,7 +149,7 @@ class Foo:
<_ as IntoPy<PyObject>>::into_py("s", py).into_bound(py),
<_ as IntoPy<PyObject>>::into_py(1.23, py).into_bound(py),
);
let kwargs = [("d", 1), ("e", 42)].into_py_dict(py);
let kwargs = [("d", 1), ("e", 42)].into_py_dict(py).unwrap();

b.iter(|| {
for _ in 0..1000 {
Expand Down
4 changes: 2 additions & 2 deletions pyo3-benches/benches/bench_decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use pyo3::types::PyDict;
fn decimal_via_extract(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let locals = PyDict::new(py);
py.run_bound(
r#"
py.run(
cr#"
import decimal
py_dec = decimal.Decimal("0.0")
"#,
Expand Down
40 changes: 30 additions & 10 deletions pyo3-benches/benches/bench_dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use pyo3::{prelude::*, types::PyMapping};
fn iter_dict(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
let mut sum = 0;
b.iter(|| {
for (k, _v) in &dict {
Expand All @@ -23,14 +26,22 @@ fn iter_dict(b: &mut Bencher<'_>) {
fn dict_new(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 50_000;
b.iter_with_large_drop(|| (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py));
b.iter_with_large_drop(|| {
(0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap()
});
});
}

fn dict_get_item(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 50_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
let mut sum = 0;
b.iter(|| {
for i in 0..LEN {
Expand All @@ -48,32 +59,43 @@ fn dict_get_item(b: &mut Bencher<'_>) {
fn extract_hashmap(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
b.iter(|| HashMap::<u64, u64>::extract_bound(&dict));
});
}

fn extract_btreemap(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
b.iter(|| BTreeMap::<u64, u64>::extract_bound(&dict));
});
}

#[cfg(feature = "hashbrown")]
fn extract_hashbrown_map(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = (0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
b.iter(|| hashbrown::HashMap::<u64, u64>::extract_bound(&dict));
});
}

fn mapping_from_dict(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let dict = &(0..LEN as u64).map(|i| (i, i * 2)).into_py_dict(py);
let dict = &(0..LEN as u64)
.map(|i| (i, i * 2))
.into_py_dict(py)
.unwrap();
b.iter(|| black_box(dict).downcast::<PyMapping>().unwrap());
});
}
Expand All @@ -85,8 +107,6 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("extract_hashmap", extract_hashmap);
c.bench_function("extract_btreemap", extract_btreemap);
c.bench_function("mapping_from_dict", mapping_from_dict);

#[cfg(feature = "hashbrown")]
c.bench_function("extract_hashbrown_map", extract_hashbrown_map);
}

Expand Down
6 changes: 3 additions & 3 deletions pyo3-benches/benches/bench_extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use pyo3::{

fn extract_str_extract_success(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let s = PyString::new_bound(py, "Hello, World!").into_any();
let s = PyString::new(py, "Hello, World!").into_any();

bench.iter(|| black_box(&s).extract::<&str>().unwrap());
});
Expand All @@ -26,10 +26,10 @@ fn extract_str_extract_fail(bench: &mut Bencher<'_>) {
});
}

#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]
#[cfg(any(Py_3_10))]
fn extract_str_downcast_success(bench: &mut Bencher<'_>) {
Python::with_gil(|py| {
let s = PyString::new_bound(py, "Hello, World!").into_any();
let s = PyString::new(py, "Hello, World!").into_any();

bench.iter(|| {
let py_str = black_box(&s).downcast::<PyString>().unwrap();
Expand Down
8 changes: 4 additions & 4 deletions pyo3-benches/benches/bench_frompyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ enum ManyTypes {

fn enum_from_pyobject(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let any = PyString::new_bound(py, "hello world").into_any();
let any = PyString::new(py, "hello world").into_any();

b.iter(|| black_box(&any).extract::<ManyTypes>().unwrap());
})
Expand All @@ -41,15 +41,15 @@ fn list_via_extract(b: &mut Bencher<'_>) {

fn not_a_list_via_downcast(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let any = PyString::new_bound(py, "foobar").into_any();
let any = PyString::new(py, "foobar").into_any();

b.iter(|| black_box(&any).downcast::<PyList>().unwrap_err());
})
}

fn not_a_list_via_extract(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let any = PyString::new_bound(py, "foobar").into_any();
let any = PyString::new(py, "foobar").into_any();

b.iter(|| black_box(&any).extract::<Bound<'_, PyList>>().unwrap_err());
})
Expand All @@ -63,7 +63,7 @@ enum ListOrNotList<'a> {

fn not_a_list_via_extract_enum(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let any = PyString::new_bound(py, "foobar").into_any();
let any = PyString::new(py, "foobar").into_any();

b.iter(|| match black_box(&any).extract::<ListOrNotList<'_>>() {
Ok(ListOrNotList::List(_list)) => panic!(),
Expand Down
4 changes: 2 additions & 2 deletions pyo3-benches/benches/bench_intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ use pyo3::intern;

fn getattr_direct(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let sys = &py.import_bound("sys").unwrap();
let sys = &py.import("sys").unwrap();

b.iter(|| black_box(sys).getattr("version").unwrap());
});
}

fn getattr_intern(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
let sys = &py.import_bound("sys").unwrap();
let sys = &py.import("sys").unwrap();

b.iter(|| black_box(sys).getattr(intern!(py, "version")).unwrap());
});
Expand Down
4 changes: 2 additions & 2 deletions pyo3-benches/benches/bench_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn list_get_item(b: &mut Bencher<'_>) {
});
}

#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, Py_GIL_DISABLED)))]
fn list_get_item_unchecked(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 50_000;
Expand Down Expand Up @@ -67,7 +67,7 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("iter_list", iter_list);
c.bench_function("list_new", list_new);
c.bench_function("list_get_item", list_get_item);
#[cfg(not(Py_LIMITED_API))]
#[cfg(not(any(Py_LIMITED_API, Py_GIL_DISABLED)))]
c.bench_function("list_get_item_unchecked", list_get_item_unchecked);
c.bench_function("sequence_from_list", sequence_from_list);
}
Expand Down
13 changes: 5 additions & 8 deletions pyo3-benches/benches/bench_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ fn set_new(b: &mut Bencher<'_>) {
// Create Python objects up-front, so that the benchmark doesn't need to include
// the cost of allocating LEN Python integers
let elements: Vec<PyObject> = (0..LEN).map(|i| i.into_py(py)).collect();
b.iter_with_large_drop(|| PySet::new_bound(py, &elements).unwrap());
b.iter_with_large_drop(|| PySet::new(py, &elements).unwrap());
});
}

fn iter_set(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let set = PySet::new_bound(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
let set = PySet::new(py, &(0..LEN).collect::<Vec<_>>()).unwrap();
let mut sum = 0;
b.iter(|| {
for x in &set {
Expand All @@ -34,7 +34,7 @@ fn iter_set(b: &mut Bencher<'_>) {
fn extract_hashset(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let any = PySet::new_bound(py, &(0..LEN).collect::<Vec<_>>())
let any = PySet::new(py, &(0..LEN).collect::<Vec<_>>())
.unwrap()
.into_any();
b.iter_with_large_drop(|| black_box(&any).extract::<HashSet<u64>>());
Expand All @@ -44,18 +44,17 @@ fn extract_hashset(b: &mut Bencher<'_>) {
fn extract_btreeset(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let any = PySet::new_bound(py, &(0..LEN).collect::<Vec<_>>())
let any = PySet::new(py, &(0..LEN).collect::<Vec<_>>())
.unwrap()
.into_any();
b.iter_with_large_drop(|| black_box(&any).extract::<BTreeSet<u64>>());
});
}

#[cfg(feature = "hashbrown")]
fn extract_hashbrown_set(b: &mut Bencher<'_>) {
Python::with_gil(|py| {
const LEN: usize = 100_000;
let any = PySet::new_bound(py, &(0..LEN).collect::<Vec<_>>())
let any = PySet::new(py, &(0..LEN).collect::<Vec<_>>())
.unwrap()
.into_any();
b.iter_with_large_drop(|| black_box(&any).extract::<hashbrown::HashSet<u64>>());
Expand All @@ -67,8 +66,6 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("iter_set", iter_set);
c.bench_function("extract_hashset", extract_hashset);
c.bench_function("extract_btreeset", extract_btreeset);

#[cfg(feature = "hashbrown")]
c.bench_function("extract_hashbrown_set", extract_hashbrown_set);
}

Expand Down
Loading