Skip to content

Commit 7257785

Browse files
authored
Merge pull request RustPython#2523 from RustPython/fix-cpy-microbenchmarks
Fix CPython microbenchmarks
2 parents 605a353 + 3c9bcf3 commit 7257785

File tree

1 file changed

+51
-15
lines changed

1 file changed

+51
-15
lines changed

benches/microbenchmarks.rs

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use cpython::Python;
21
use criterion::measurement::WallTime;
32
use criterion::{
43
criterion_group, criterion_main, BatchSize, BenchmarkGroup, BenchmarkId, Criterion, Throughput,
@@ -19,31 +18,32 @@ pub struct MicroBenchmark {
1918

2019
fn bench_cpython_code(group: &mut BenchmarkGroup<WallTime>, bench: &MicroBenchmark) {
2120
let gil = cpython::Python::acquire_gil();
22-
let python = gil.python();
21+
let py = gil.python();
2322

24-
let bench_func = |(python, code): (Python, String)| {
25-
let res: cpython::PyResult<()> = python.run(&code, None, None);
23+
let bench_func = |(code, globals, locals)| {
24+
let res = cpy_run_code(py, &code, &globals, &locals);
2625
if let Err(e) = res {
27-
e.print(python);
26+
e.print(py);
2827
panic!("Error running microbenchmark")
2928
}
3029
};
3130

3231
let bench_setup = |iterations| {
33-
let code = if let Some(idx) = iterations {
34-
// We can't easily modify the locals when running cPython. So we just add the
35-
// loop iterations at the top of the code...
36-
format!("ITERATIONS = {}\n{}", idx, bench.code)
37-
} else {
38-
(&bench.code).to_string()
39-
};
32+
let globals = cpython::PyDict::new(py);
33+
let locals = cpython::PyDict::new(py);
34+
if let Some(idx) = iterations {
35+
globals.set_item(py, "ITERATIONS", idx).unwrap();
36+
}
4037

41-
let res: cpython::PyResult<()> = python.run(&bench.setup, None, None);
38+
let res = py.run(&bench.setup, Some(&globals), Some(&locals));
4239
if let Err(e) = res {
43-
e.print(python);
40+
e.print(py);
4441
panic!("Error running microbenchmark setup code")
4542
}
46-
(python, code)
43+
let code = std::ffi::CString::new(&*bench.code).unwrap();
44+
let name = std::ffi::CString::new(&*bench.name).unwrap();
45+
let code = cpy_compile_code(py, &code, &name).unwrap();
46+
(code, globals, locals)
4747
};
4848

4949
if bench.iterate {
@@ -64,6 +64,42 @@ fn bench_cpython_code(group: &mut BenchmarkGroup<WallTime>, bench: &MicroBenchma
6464
}
6565
}
6666

67+
unsafe fn cpy_res(
68+
py: cpython::Python<'_>,
69+
x: *mut python3_sys::PyObject,
70+
) -> cpython::PyResult<cpython::PyObject> {
71+
cpython::PyObject::from_owned_ptr_opt(py, x).ok_or_else(|| cpython::PyErr::fetch(py))
72+
}
73+
74+
fn cpy_compile_code(
75+
py: cpython::Python<'_>,
76+
s: &std::ffi::CStr,
77+
fname: &std::ffi::CStr,
78+
) -> cpython::PyResult<cpython::PyObject> {
79+
unsafe {
80+
let res =
81+
python3_sys::Py_CompileString(s.as_ptr(), fname.as_ptr(), python3_sys::Py_file_input);
82+
cpy_res(py, res)
83+
}
84+
}
85+
86+
fn cpy_run_code(
87+
py: cpython::Python<'_>,
88+
code: &cpython::PyObject,
89+
locals: &cpython::PyDict,
90+
globals: &cpython::PyDict,
91+
) -> cpython::PyResult<cpython::PyObject> {
92+
use cpython::PythonObject;
93+
unsafe {
94+
let res = python3_sys::PyEval_EvalCode(
95+
code.as_ptr(),
96+
locals.as_object().as_ptr(),
97+
globals.as_object().as_ptr(),
98+
);
99+
cpy_res(py, res)
100+
}
101+
}
102+
67103
fn bench_rustpy_code(group: &mut BenchmarkGroup<WallTime>, bench: &MicroBenchmark) {
68104
let mut settings = PySettings::default();
69105
settings.path_list.push("Lib/".to_string());

0 commit comments

Comments
 (0)