Skip to content

Commit 1f7c1fc

Browse files
committed
move benches to subdirectory
1 parent 1fa46d0 commit 1f7c1fc

20 files changed

+198
-73
lines changed

.github/workflows/gh-pages.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
runs-on: ubuntu-latest
6161
steps:
6262
- uses: actions/checkout@v3
63-
63+
- uses: actions/setup-python@v4
6464
- uses: dtolnay/rust-toolchain@stable
6565

6666
- uses: actions/cache@v3
@@ -74,8 +74,10 @@ jobs:
7474

7575
- name: Run benchmarks
7676
run: |
77-
for bench in call dict gil list pyclass pyobject set tuple; do
78-
cargo bench --features hashbrown --bench "bench_$bench" -- --output-format bencher | tee -a output.txt
77+
python -m pip install --upgrade pip && pip install nox
78+
for bench in pyo3-benches/benches/*.rs; do
79+
bench_name=$(basename "$bench" .rs)
80+
nox -s bench -- --bench "$bench_name" -- --output-format bencher | tee -a output.txt
7981
done
8082
8183
# Download previous benchmark result from cache (if exists)

Cargo.toml

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ serde = { version = "1.0", optional = true }
4444
[dev-dependencies]
4545
assert_approx_eq = "1.1.0"
4646
chrono = { version = "0.4" }
47-
criterion = "0.3.5"
4847
# Required for "and $N others" normalization
4948
trybuild = ">=1.0.70"
5049
rustversion = "1.0"
@@ -114,65 +113,6 @@ full = [
114113
"rust_decimal",
115114
]
116115

117-
[[bench]]
118-
name = "bench_any"
119-
harness = false
120-
121-
[[bench]]
122-
name = "bench_call"
123-
harness = false
124-
125-
[[bench]]
126-
name = "bench_err"
127-
harness = false
128-
129-
[[bench]]
130-
name = "bench_decimal"
131-
harness = false
132-
required-features = ["rust_decimal"]
133-
134-
[[bench]]
135-
name = "bench_dict"
136-
harness = false
137-
138-
[[bench]]
139-
name = "bench_frompyobject"
140-
harness = false
141-
required-features = ["macros"]
142-
143-
[[bench]]
144-
name = "bench_gil"
145-
harness = false
146-
147-
[[bench]]
148-
name = "bench_list"
149-
harness = false
150-
151-
[[bench]]
152-
name = "bench_pyclass"
153-
harness = false
154-
required-features = ["macros"]
155-
156-
[[bench]]
157-
name = "bench_pyobject"
158-
harness = false
159-
160-
[[bench]]
161-
name = "bench_set"
162-
harness = false
163-
164-
[[bench]]
165-
name = "bench_tuple"
166-
harness = false
167-
168-
[[bench]]
169-
name = "bench_intern"
170-
harness = false
171-
172-
[[bench]]
173-
name = "bench_extract"
174-
harness = false
175-
176116
[workspace]
177117
members = [
178118
"pyo3-ffi",

Contributing.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,9 @@ CI tests both the most recent stable Rust version and the minimum supported Rust
165165

166166
PyO3 has two sets of benchmarks for evaluating some aspects of its performance. The benchmark suite is currently very small - please open PRs with new benchmarks if you're interested in helping to expand it!
167167

168-
First, there are Rust-based benchmarks located in the `benches` subdirectory. As long as you have a nightly rust compiler available on your system, you can run these benchmarks with:
168+
First, there are Rust-based benchmarks located in the `pyo3-benches` subdirectory. You can run these benchmarks with:
169169

170-
cargo +nightly bench
170+
nox -s bench
171171

172172
Second, there is a Python-based benchmark contained in the `pytests` subdirectory. You can read more about it [here](pytests).
173173

noxfile.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def fmt(session: nox.Session):
7575
@nox.session(name="fmt-rust", venv_backend="none")
7676
def fmt_rust(session: nox.Session):
7777
_run_cargo(session, "fmt", "--all", "--check")
78-
_run_cargo(session, "fmt", *_FFI_CHECK, "--all", "--check")
78+
_run_cargo(session, "fmt", _FFI_CHECK, "--all", "--check")
7979

8080

8181
@nox.session(name="fmt-py")
@@ -86,7 +86,7 @@ def fmt_py(session: nox.Session):
8686

8787
@nox.session(name="clippy", venv_backend="none")
8888
def clippy(session: nox.Session) -> bool:
89-
if not _clippy(session):
89+
if not _clippy(session) and _clippy_additional_workspaces(session):
9090
session.error("one or more jobs failed")
9191

9292

@@ -110,6 +110,33 @@ def _clippy(session: nox.Session, *, env: Dict[str, str] = None) -> bool:
110110
return success
111111

112112

113+
def _clippy_additional_workspaces(session: nox.Session) -> bool:
114+
# pyo3-benches and pyo3-ffi-check are in isolated workspaces so that their
115+
# dependencies do not interact with MSRV
116+
117+
success = True
118+
try:
119+
_run_cargo(session, "clippy", _BENCHES)
120+
except Exception:
121+
success = False
122+
123+
# Run pyo3-ffi-check only on when not cross-compiling, because it needs to
124+
# have Python headers to feed to bindgen which gets messy when cross-compiling.
125+
target = os.environ.get("CARGO_BUILD_TARGET")
126+
if target is None or _get_rust_default_target() == target:
127+
try:
128+
_build_docs_for_ffi_check(session)
129+
_run_cargo(session, "clippy", _FFI_CHECK, "--workspace", "--all-targets")
130+
except Exception:
131+
success = False
132+
return success
133+
134+
135+
@nox.session(venv_backend="none")
136+
def bench(session: nox.Session) -> bool:
137+
_run_cargo(session, "bench", _BENCHES, *session.posargs)
138+
139+
113140
@nox.session(name="clippy-all", venv_backend="none")
114141
def clippy_all(session: nox.Session) -> None:
115142
success = True
@@ -119,6 +146,7 @@ def _clippy_with_config(env: Dict[str, str]) -> None:
119146
success &= _clippy(session, env=env)
120147

121148
_for_all_version_configs(session, _clippy_with_config)
149+
success &= _clippy_additional_workspaces(session)
122150

123151
if not success:
124152
session.error("one or more jobs failed")
@@ -376,7 +404,7 @@ def address_sanitizer(session: nox.Session):
376404
"test",
377405
"--release",
378406
"-Zbuild-std",
379-
f"--target={_get_rust_target()}",
407+
f"--target={_get_rust_default_target()}",
380408
"--",
381409
"--test-threads=1",
382410
env={
@@ -533,9 +561,13 @@ def load_pkg_versions():
533561

534562
@nox.session(name="ffi-check")
535563
def ffi_check(session: nox.Session):
536-
_run_cargo(session, "doc", *_FFI_CHECK, "-p", "pyo3-ffi", "--no-deps")
537-
_run_cargo(session, "clippy", "--workspace", "--all-targets", *_FFI_CHECK)
538-
_run_cargo(session, "run", *_FFI_CHECK)
564+
_build_docs_for_ffi_check(session)
565+
_run_cargo(session, "run", _FFI_CHECK)
566+
567+
568+
def _build_docs_for_ffi_check(session: nox.Session) -> None:
569+
# pyo3-ffi-check needs to scrape docs of pyo3-ffi
570+
_run_cargo(session, "doc", _FFI_CHECK, "-p", "pyo3-ffi", "--no-deps")
539571

540572

541573
@lru_cache()
@@ -554,7 +586,7 @@ def _get_rust_version() -> Tuple[int, int, int, List[str]]:
554586
return (*map(int, version_number.split(".")), extra)
555587

556588

557-
def _get_rust_target() -> str:
589+
def _get_rust_default_target() -> str:
558590
for line in _get_rust_info():
559591
if line.startswith(_HOST_LINE_START):
560592
return line[len(_HOST_LINE_START) :].strip()
@@ -692,4 +724,5 @@ def _job_with_config(implementation, version) -> bool:
692724
_job_with_config("PyPy", version)
693725

694726

695-
_FFI_CHECK = ("--manifest-path", "pyo3-ffi-check/Cargo.toml")
727+
_BENCHES = "--manifest-path=pyo3-benches/Cargo.toml"
728+
_FFI_CHECK = "--manifest-path=pyo3-ffi-check/Cargo.toml"

pyo3-benches/Cargo.toml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
[package]
2+
name = "pyo3-benches"
3+
version = "0.1.0"
4+
description = "In-tree benchmarks for the PyO3 project"
5+
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
6+
edition = "2021"
7+
publish = false
8+
9+
[dependencies]
10+
pyo3 = { path = "../", features = ["auto-initialize"] }
11+
12+
[dev-dependencies]
13+
criterion = "0.3.5"
14+
15+
[[bench]]
16+
name = "bench_any"
17+
harness = false
18+
19+
[[bench]]
20+
name = "bench_call"
21+
harness = false
22+
23+
[[bench]]
24+
name = "bench_comparisons"
25+
harness = false
26+
27+
[[bench]]
28+
name = "bench_err"
29+
harness = false
30+
31+
[[bench]]
32+
name = "bench_decimal"
33+
harness = false
34+
required-features = ["pyo3/rust_decimal"]
35+
36+
[[bench]]
37+
name = "bench_dict"
38+
harness = false
39+
required-features = ["pyo3/hashbrown"]
40+
41+
[[bench]]
42+
name = "bench_frompyobject"
43+
harness = false
44+
required-features = ["pyo3/macros"]
45+
46+
[[bench]]
47+
name = "bench_gil"
48+
harness = false
49+
50+
[[bench]]
51+
name = "bench_list"
52+
harness = false
53+
54+
[[bench]]
55+
name = "bench_pyclass"
56+
harness = false
57+
required-features = ["pyo3/macros"]
58+
59+
[[bench]]
60+
name = "bench_pyobject"
61+
harness = false
62+
63+
[[bench]]
64+
name = "bench_set"
65+
harness = false
66+
required-features = ["pyo3/hashbrown"]
67+
68+
[[bench]]
69+
name = "bench_tuple"
70+
harness = false
71+
72+
[[bench]]
73+
name = "bench_intern"
74+
harness = false
75+
76+
[[bench]]
77+
name = "bench_extract"
78+
harness = false
79+
80+
[workspace]
File renamed without changes.
File renamed without changes.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
2+
3+
use pyo3::{prelude::*, pyclass::CompareOp, Python};
4+
5+
#[pyclass]
6+
struct OrderedDunderMethods(i64);
7+
8+
#[pymethods]
9+
impl OrderedDunderMethods {
10+
fn __lt__(&self, other: &Self) -> bool {
11+
self.0 < other.0
12+
}
13+
14+
fn __le__(&self, other: &Self) -> bool {
15+
self.0 <= other.0
16+
}
17+
18+
fn __eq__(&self, other: &Self) -> bool {
19+
self.0 == other.0
20+
}
21+
22+
fn __ne__(&self, other: &Self) -> bool {
23+
self.0 != other.0
24+
}
25+
26+
fn __gt__(&self, other: &Self) -> bool {
27+
self.0 > other.0
28+
}
29+
30+
fn __ge__(&self, other: &Self) -> bool {
31+
self.0 >= other.0
32+
}
33+
}
34+
35+
#[pyclass]
36+
#[derive(PartialEq, Eq, PartialOrd, Ord)]
37+
struct OrderedRichcmp(i64);
38+
39+
#[pymethods]
40+
impl OrderedRichcmp {
41+
fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
42+
op.matches(self.cmp(other))
43+
}
44+
}
45+
46+
fn bench_ordered_dunder_methods(b: &mut Bencher<'_>) {
47+
Python::with_gil(|py| {
48+
let obj1 = Py::new(py, OrderedDunderMethods(0)).unwrap().into_ref(py);
49+
let obj2 = Py::new(py, OrderedDunderMethods(1)).unwrap().into_ref(py);
50+
51+
b.iter(|| obj2.gt(obj1).unwrap());
52+
});
53+
}
54+
55+
fn bench_ordered_richcmp(b: &mut Bencher<'_>) {
56+
Python::with_gil(|py| {
57+
let obj1 = Py::new(py, OrderedRichcmp(0)).unwrap().into_ref(py);
58+
let obj2 = Py::new(py, OrderedRichcmp(1)).unwrap().into_ref(py);
59+
60+
b.iter(|| obj2.gt(obj1).unwrap());
61+
});
62+
}
63+
64+
fn criterion_benchmark(c: &mut Criterion) {
65+
c.bench_function("ordered_dunder_methods", bench_ordered_dunder_methods);
66+
c.bench_function("ordered_richcmp", bench_ordered_richcmp);
67+
}
68+
69+
criterion_group!(benches, criterion_benchmark);
70+
criterion_main!(benches);
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)