From db6fa17ffedb7f4439b3ffdba6330bb157a47e24 Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Mon, 5 Apr 2021 09:49:16 -0500 Subject: [PATCH] Don't recompile CPython microbenchmarks every time --- benches/microbenchmarks.rs | 44 ++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/benches/microbenchmarks.rs b/benches/microbenchmarks.rs index a344e3aec..d0f23f160 100644 --- a/benches/microbenchmarks.rs +++ b/benches/microbenchmarks.rs @@ -7,7 +7,7 @@ use rustpython_vm::pyobject::ItemProtocol; use rustpython_vm::pyobject::PyResult; use rustpython_vm::{InitParameter, Interpreter, PySettings}; use std::path::{Path, PathBuf}; -use std::{fs, io}; +use std::{ffi, fs, io}; pub struct MicroBenchmark { name: String, @@ -20,8 +20,16 @@ fn bench_cpython_code(group: &mut BenchmarkGroup, bench: &MicroBenchma let gil = cpython::Python::acquire_gil(); let py = gil.python(); - let bench_func = |(code, globals, locals)| { - let res = cpy_run_code(py, &code, &globals, &locals); + let setup_code = ffi::CString::new(&*bench.setup).unwrap(); + let setup_name = ffi::CString::new(format!("{}_setup", bench.name)).unwrap(); + let setup_code = cpy_compile_code(py, &setup_code, &setup_name).unwrap(); + + let code = ffi::CString::new(&*bench.code).unwrap(); + let name = ffi::CString::new(&*bench.name).unwrap(); + let code = cpy_compile_code(py, &code, &name).unwrap(); + + let bench_func = |(globals, locals): &mut (cpython::PyDict, cpython::PyDict)| { + let res = cpy_run_code(py, &code, globals, locals); if let Err(e) = res { e.print(py); panic!("Error running microbenchmark") @@ -30,36 +38,36 @@ fn bench_cpython_code(group: &mut BenchmarkGroup, bench: &MicroBenchma let bench_setup = |iterations| { let globals = cpython::PyDict::new(py); + // setup the __builtins__ attribute - no other way to do this (other than manually) as far + // as I can tell + let _ = py.run("", Some(&globals), None); let locals = cpython::PyDict::new(py); if let Some(idx) = iterations { globals.set_item(py, "ITERATIONS", idx).unwrap(); } - let res = py.run(&bench.setup, Some(&globals), Some(&locals)); + let res = cpy_run_code(py, &setup_code, &globals, &locals); if let Err(e) = res { e.print(py); panic!("Error running microbenchmark setup code") } - let code = std::ffi::CString::new(&*bench.code).unwrap(); - let name = std::ffi::CString::new(&*bench.name).unwrap(); - let code = cpy_compile_code(py, &code, &name).unwrap(); - (code, globals, locals) + (globals, locals) }; if bench.iterate { for idx in (100..=1_000).step_by(200) { group.throughput(Throughput::Elements(idx as u64)); group.bench_with_input(BenchmarkId::new("cpython", &bench.name), &idx, |b, idx| { - b.iter_batched( + b.iter_batched_ref( || bench_setup(Some(*idx)), bench_func, - BatchSize::PerIteration, + BatchSize::LargeInput, ); }); } } else { group.bench_function(BenchmarkId::new("cpython", &bench.name), move |b| { - b.iter_batched(|| bench_setup(None), bench_func, BatchSize::PerIteration); + b.iter_batched_ref(|| bench_setup(None), bench_func, BatchSize::LargeInput); }); } } @@ -73,8 +81,8 @@ unsafe fn cpy_res( fn cpy_compile_code( py: cpython::Python<'_>, - s: &std::ffi::CStr, - fname: &std::ffi::CStr, + s: &ffi::CStr, + fname: &ffi::CStr, ) -> cpython::PyResult { unsafe { let res = @@ -114,8 +122,8 @@ fn bench_rustpy_code(group: &mut BenchmarkGroup, bench: &MicroBenchmar .compile(&bench.code, Mode::Exec, bench.name.to_owned()) .expect("Error compiling bench code"); - let bench_func = |(scope, bench_code)| { - let res: PyResult = vm.run_code_obj(bench_code, scope); + let bench_func = |scope| { + let res: PyResult = vm.run_code_obj(bench_code.clone(), scope); vm.unwrap_pyresult(res); }; @@ -129,7 +137,7 @@ fn bench_rustpy_code(group: &mut BenchmarkGroup, bench: &MicroBenchmar } let setup_result = vm.run_code_obj(setup_code.clone(), scope.clone()); vm.unwrap_pyresult(setup_result); - (scope, bench_code.clone()) + scope }; if bench.iterate { @@ -142,14 +150,14 @@ fn bench_rustpy_code(group: &mut BenchmarkGroup, bench: &MicroBenchmar b.iter_batched( || bench_setup(Some(*idx)), bench_func, - BatchSize::PerIteration, + BatchSize::LargeInput, ); }, ); } } else { group.bench_function(BenchmarkId::new("rustpython", &bench.name), move |b| { - b.iter_batched(|| bench_setup(None), bench_func, BatchSize::PerIteration); + b.iter_batched(|| bench_setup(None), bench_func, BatchSize::LargeInput); }); } })