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
86 changes: 68 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ rustpython-format = { git = "https://github.com/RustPython/Parser.git", rev = "2
# rustpython-format = { path = "../RustPython-parser/format" }

ahash = "0.8.3"
anyhow = "1.0.45"
ascii = "1.0"
atty = "0.2.14"
bitflags = "2.4.0"
Expand Down Expand Up @@ -118,9 +117,8 @@ libc = { workspace = true }
rustyline = { workspace = true }

[dev-dependencies]
cpython = "0.7.0"
criterion = "0.3.5"
python3-sys = "0.7.1"
criterion = { version = "0.3.5", features = ["html_reports"] }
pyo3 = { version = "0.20.2", features = ["auto-initialize"] }

[[bench]]
name = "execution"
Expand Down
84 changes: 29 additions & 55 deletions benches/execution.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
use criterion::measurement::WallTime;
use criterion::{
criterion_group, criterion_main, Bencher, BenchmarkGroup, BenchmarkId, Criterion, Throughput,
black_box, criterion_group, criterion_main, Bencher, BenchmarkGroup, BenchmarkId, Criterion,
Throughput,
};
use rustpython_compiler::Mode;
use rustpython_parser::ast;
use rustpython_parser::Parse;
use rustpython_vm::{Interpreter, PyResult};
use rustpython_vm::{Interpreter, PyResult, Settings};
use std::collections::HashMap;
use std::path::Path;

fn bench_cpython_code(b: &mut Bencher, source: &str) {
let gil = cpython::Python::acquire_gil();
let python = gil.python();

b.iter(|| {
let res: cpython::PyResult<()> = python.run(source, None, None);
if let Err(e) = res {
e.print(python);
panic!("Error running source")
}
});
pyo3::Python::with_gil(|py| {
b.iter(|| {
let module =
pyo3::types::PyModule::from_code(py, source, "", "").expect("Error running source");
black_box(module);
})
})
}

fn bench_rustpy_code(b: &mut Bencher, name: &str, source: &str) {
// NOTE: Take long time.
Interpreter::without_stdlib(Default::default()).enter(|vm| {
let mut settings = Settings::default();
settings.path_list.push("Lib/".to_string());
settings.dont_write_bytecode = true;
settings.no_user_site = true;
Interpreter::without_stdlib(settings).enter(|vm| {
// Note: bench_cpython is both compiling and executing the code.
// As such we compile the code in the benchmark loop as well.
b.iter(|| {
Expand All @@ -36,16 +38,12 @@ fn bench_rustpy_code(b: &mut Bencher, name: &str, source: &str) {
})
}

pub fn benchmark_file_execution(
group: &mut BenchmarkGroup<WallTime>,
name: &str,
contents: &String,
) {
pub fn benchmark_file_execution(group: &mut BenchmarkGroup<WallTime>, name: &str, contents: &str) {
group.bench_function(BenchmarkId::new(name, "cpython"), |b| {
bench_cpython_code(b, &contents)
bench_cpython_code(b, contents)
});
group.bench_function(BenchmarkId::new(name, "rustpython"), |b| {
bench_rustpy_code(b, name, &contents)
bench_rustpy_code(b, name, contents)
});
}

Expand All @@ -55,44 +53,20 @@ pub fn benchmark_file_parsing(group: &mut BenchmarkGroup<WallTime>, name: &str,
b.iter(|| ast::Suite::parse(contents, name).unwrap())
});
group.bench_function(BenchmarkId::new("cpython", name), |b| {
let gil = cpython::Python::acquire_gil();
let py = gil.python();

let code = std::ffi::CString::new(contents).unwrap();
let fname = cpython::PyString::new(py, name);

b.iter(|| parse_program_cpython(py, &code, &fname))
pyo3::Python::with_gil(|py| {
let builtins =
pyo3::types::PyModule::import(py, "builtins").expect("Failed to import builtins");
let compile = builtins.getattr("compile").expect("no compile in builtins");
b.iter(|| {
let x = compile
.call1((contents, name, "exec"))
.expect("Failed to parse code");
black_box(x);
})
})
});
}

fn parse_program_cpython(
py: cpython::Python<'_>,
code: &std::ffi::CStr,
fname: &cpython::PyString,
) {
extern "C" {
fn PyArena_New() -> *mut python3_sys::PyArena;
fn PyArena_Free(arena: *mut python3_sys::PyArena);
}
use cpython::PythonObject;
let fname = fname.as_object();
unsafe {
let arena = PyArena_New();
assert!(!arena.is_null());
let ret = python3_sys::PyParser_ASTFromStringObject(
code.as_ptr() as _,
fname.as_ptr(),
python3_sys::Py_file_input,
std::ptr::null_mut(),
arena,
);
if ret.is_null() {
cpython::PyErr::fetch(py).print(py);
}
PyArena_Free(arena);
}
}

pub fn benchmark_pystone(group: &mut BenchmarkGroup<WallTime>, contents: String) {
// Default is 50_000. This takes a while, so reduce it to 30k.
for idx in (10_000..=30_000).step_by(10_000) {
Expand Down
Loading