From 5788e7bf8e1e0019e47f24ad6521c5836f3b146e Mon Sep 17 00:00:00 2001 From: Tom Forbes Date: Thu, 10 Dec 2020 23:24:10 +0000 Subject: [PATCH] Refactor benchmarking suite to use Criterion --- .gitignore | 1 + Cargo.lock | 185 ++++++++++++++++++ Cargo.toml | 17 +- benches/README.md | 38 ++++ .../benchmarks/mandelbrot.py | 0 {benchmarks => benches}/benchmarks/minidom.py | 0 {benchmarks => benches}/benchmarks/nbody.py | 46 ++--- {benchmarks => benches}/benchmarks/pystone.py | 29 +-- {benchmarks => benches}/benchmarks/strings.py | 0 benches/execution.rs | 67 +++++++ benches/parsing.rs | 45 +++++ {benchmarks => benches}/test_benchmarks.py | 0 benchmarks/README.md | 22 --- benchmarks/bench.rs | 118 ----------- 14 files changed, 370 insertions(+), 198 deletions(-) create mode 100644 benches/README.md rename {benchmarks => benches}/benchmarks/mandelbrot.py (100%) rename {benchmarks => benches}/benchmarks/minidom.py (100%) rename {benchmarks => benches}/benchmarks/nbody.py (78%) rename {benchmarks => benches}/benchmarks/pystone.py (89%) rename {benchmarks => benches}/benchmarks/strings.py (100%) create mode 100644 benches/execution.rs create mode 100644 benches/parsing.rs rename {benchmarks => benches}/test_benchmarks.py (100%) delete mode 100644 benchmarks/README.md delete mode 100644 benchmarks/bench.rs diff --git a/.gitignore b/.gitignore index 270758d50..32d95e9cd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ flame.txt flamescope.json /wapm.lock /wapm_packages +/.cargo/config diff --git a/Cargo.lock b/Cargo.lock index fa604124c..a2379c202 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -243,6 +243,15 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "cast" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +dependencies = [ + "rustc_version", +] + [[package]] name = "cc" version = "1.0.66" @@ -305,6 +314,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "const_fn" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -454,6 +469,77 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "criterion" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" +dependencies = [ + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static 1.4.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +dependencies = [ + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils", + "lazy_static 1.4.0", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.1" @@ -802,6 +888,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "half" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" + [[package]] name = "hashbrown" version = "0.9.1" @@ -1093,6 +1185,15 @@ version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.4.3" @@ -1233,6 +1334,12 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -1351,6 +1458,18 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +[[package]] +name = "plotters" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" +dependencies = [ + "js-sys", + "num-traits", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "pmutil" version = "0.5.3" @@ -1475,6 +1594,31 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static 1.4.0", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -1595,6 +1739,7 @@ dependencies = [ "cfg-if 0.1.10", "clap", "cpython", + "criterion", "dirs-next", "env_logger", "flame", @@ -1863,6 +2008,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.19" @@ -1915,6 +2069,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "serde_cbor" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.118" @@ -2196,6 +2360,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb4fa83bb73adf1c7219f4fe4bf3c0ac5635e4e51e070fad5df745a41bedfb8" +[[package]] +name = "tinytemplate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.1.0" @@ -2434,6 +2608,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8e76fae08f03f96e166d2dfda232190638c10e0383841252416f9cfe2ae60e6" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 744ddd336..618f53aa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,6 @@ members = [ "derive", "jit", "parser", "vm", "vm/pylib-crate", "wasm/lib", ] -[[bench]] -name = "bench" -path = "./benchmarks/bench.rs" - [features] default = ["threading", "pylib"] flame-it = ["rustpython-vm/flame-it", "flame", "flamescope"] @@ -43,11 +39,22 @@ libc = "0.2" flame = { version = "0.2", optional = true } flamescope = { version = "0.1", optional = true } +cpython = "0.5.0" + [target.'cfg(not(target_os = "wasi"))'.dependencies] rustyline = "6.0" [dev-dependencies] cpython = "0.5.0" +criterion = "0.3" + +[[bench]] +name = "parsing" +harness = false + +[[bench]] +name = "execution" +harness = false [[bin]] name = "rustpython" @@ -63,3 +70,5 @@ opt-level = 3 # crossbeam-utils = { git = "https://github.com/crossbeam-rs/crossbeam" } # socket2 = { git = "https://github.com/alexcrichton/socket2-rs" } # REDOX END + +[target.bench] diff --git a/benches/README.md b/benches/README.md new file mode 100644 index 000000000..a28f58d40 --- /dev/null +++ b/benches/README.md @@ -0,0 +1,38 @@ +# Benchmarking + +These are some files to determine performance of rustpython. + +## Usage + +Install pytest and pytest-benchmark: + + $ pip install pytest-benchmark + +Then run: + + $ pytest + +You can also benchmark the Rust benchmarks by just running +`cargo bench` from the root of the repository. To view Python tracebacks during benchmarks, +run `RUST_BACKTRACE=1 cargo bench`. + +You can bench against a specific Python version by running: + +```shell +$ PYTHON_SYS_EXECUTABLE=python3.7 cargo bench +``` + +On MacOS you will need to +add the following to a `.cargo/config` file: + +```toml +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] +``` + +## Benchmark source + +- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-python3-2.html diff --git a/benchmarks/benchmarks/mandelbrot.py b/benches/benchmarks/mandelbrot.py similarity index 100% rename from benchmarks/benchmarks/mandelbrot.py rename to benches/benchmarks/mandelbrot.py diff --git a/benchmarks/benchmarks/minidom.py b/benches/benchmarks/minidom.py similarity index 100% rename from benchmarks/benchmarks/minidom.py rename to benches/benchmarks/minidom.py diff --git a/benchmarks/benchmarks/nbody.py b/benches/benchmarks/nbody.py similarity index 78% rename from benchmarks/benchmarks/nbody.py rename to benches/benchmarks/nbody.py index b9ab142df..d9352bb2b 100644 --- a/benchmarks/benchmarks/nbody.py +++ b/benches/benchmarks/nbody.py @@ -1,22 +1,11 @@ - # The Computer Language Benchmarks Game -# https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ +# http://benchmarksgame.alioth.debian.org/ # -# originally by Kevin Carson +# contributed by Kevin Carson # modified by Tupteq, Fredrik Johansson, and Daniel Nanz -# modified by Maciej Fijalkowski -# 2to3 -# modified by Andriy Misyura -from math import sqrt - -def combinations(l): - result = [] - for x in range(len(l) - 1): - ls = l[x+1:] - for y in ls: - result.append((l[x][0],l[x][1],l[x][2],y[0],y[1],y[2])) - return result +import itertools +import sys PI = 3.14159265358979323 SOLAR_MASS = 4 * PI * PI @@ -55,41 +44,44 @@ BODIES = { [2.68067772490389322e-03 * DAYS_PER_YEAR, 1.62824170038242295e-03 * DAYS_PER_YEAR, -9.51592254519715870e-05 * DAYS_PER_YEAR], - 5.15138902046611451e-05 * SOLAR_MASS) } + 5.15138902046611451e-05 * SOLAR_MASS)} + +SYSTEM = BODIES.values() +PAIRS = list(itertools.combinations(SYSTEM, 2)) -SYSTEM = tuple(BODIES.values()) -PAIRS = tuple(combinations(SYSTEM)) def advance(dt, n, bodies=SYSTEM, pairs=PAIRS): for i in range(n): - for ([x1, y1, z1], v1, m1, [x2, y2, z2], v2, m2) in pairs: + for (([x1, y1, z1], v1, m1), + ([x2, y2, z2], v2, m2)) in pairs: dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 - dist = sqrt(dx * dx + dy * dy + dz * dz); - mag = dt / (dist*dist*dist) + mag = dt * ((dx * dx + dy * dy + dz * dz) ** (-1.5)) b1m = m1 * mag b2m = m2 * mag v1[0] -= dx * b2m v1[1] -= dy * b2m v1[2] -= dz * b2m - v2[2] += dz * b1m - v2[1] += dy * b1m v2[0] += dx * b1m + v2[1] += dy * b1m + v2[2] += dz * b1m for (r, [vx, vy, vz], m) in bodies: r[0] += dt * vx r[1] += dt * vy r[2] += dt * vz + def report_energy(bodies=SYSTEM, pairs=PAIRS, e=0.0): - for ((x1, y1, z1), v1, m1, (x2, y2, z2), v2, m2) in pairs: + for (((x1, y1, z1), v1, m1), + ((x2, y2, z2), v2, m2)) in pairs: dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 e -= (m1 * m2) / ((dx * dx + dy * dy + dz * dz) ** 0.5) for (r, [vx, vy, vz], m) in bodies: e += m * (vx * vx + vy * vy + vz * vz) / 2. - # print(f"{e}") + def offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0): for (r, [vx, vy, vz], m) in bodies: @@ -101,10 +93,12 @@ def offset_momentum(ref, bodies=SYSTEM, px=0.0, py=0.0, pz=0.0): v[1] = py / m v[2] = pz / m + def main(n, ref='sun'): offset_momentum(BODIES[ref]) report_energy() advance(0.01, n) report_energy() -main(500) + +main(int(25)) diff --git a/benchmarks/benchmarks/pystone.py b/benches/benchmarks/pystone.py similarity index 89% rename from benchmarks/benchmarks/pystone.py rename to benches/benchmarks/pystone.py index 7c122cf67..cde6b2a27 100644 --- a/benchmarks/benchmarks/pystone.py +++ b/benches/benchmarks/pystone.py @@ -41,10 +41,6 @@ Version History: """ -from __future__ import print_function - -LOOPS = 50000 - from time import time as clock __version__ = "1.1.1" @@ -68,15 +64,6 @@ class Record: TRUE = 1 FALSE = 0 -def main(loops=LOOPS): - benchtime, stones = pystones(loops) - print("Pystone(%s) time for %d passes = %f" % \ - (__version__, loops, benchtime)) - print("This machine benchmarks at %f pystones/second" % stones) - - -def pystones(loops=LOOPS): - return Proc0(loops) IntGlob = 0 BoolGlob = FALSE @@ -264,18 +251,4 @@ def Func3(EnumParIn): return FALSE if __name__ == '__main__': - import sys - def error(msg): - print(msg, end=' ', file=sys.stderr) - print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr) - sys.exit(100) - nargs = len(sys.argv) - 1 - if nargs > 1: - error("%d arguments are too many;" % nargs) - elif nargs == 1: - try: loops = int(sys.argv[1]) - except ValueError: - error("Invalid argument %r;" % sys.argv[1]) - else: - loops = LOOPS - main(loops) + Proc0(LOOPS) diff --git a/benchmarks/benchmarks/strings.py b/benches/benchmarks/strings.py similarity index 100% rename from benchmarks/benchmarks/strings.py rename to benches/benchmarks/strings.py diff --git a/benches/execution.rs b/benches/execution.rs new file mode 100644 index 000000000..3a8fa2131 --- /dev/null +++ b/benches/execution.rs @@ -0,0 +1,67 @@ +use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion, BenchmarkId, Throughput}; +use rustpython_compiler::{Mode}; +use rustpython_vm::pyobject::PyResult; +use rustpython_vm::Interpreter; + +const NBODY: &str = include_str!("./benchmarks/nbody.py"); +const MANDELBROT: &str = include_str!("./benchmarks/mandelbrot.py"); +const PYSTONE: &str = include_str!("./benchmarks/pystone.py"); + +fn bench_cpython(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") + } + }); +} + +fn bench_rustpy(b: &mut Bencher, name: &str, source: &str) { + // NOTE: Take long time. + Interpreter::default().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(|| { + let code = vm.compile(source, Mode::Exec, name.to_owned()).unwrap(); + let scope = vm.new_scope_with_builtins(); + let res: PyResult = vm.run_code_obj(code.clone(), scope); + vm.unwrap_pyresult(res); + }) + }) +} + +pub fn benchmark_file(c: &mut Criterion, name: &str, contents: &str) { + let mut group = c.benchmark_group(name); + group.bench_function(BenchmarkId::new("cpython", name), |b| bench_cpython(b, black_box(contents))); + group.bench_function(BenchmarkId::new("rustpython", name), |b| bench_rustpy(b, name, black_box(contents))); + group.finish(); +} + +pub fn benchmark_pystone(c: &mut Criterion) { + let mut group = c.benchmark_group("pystone"); + // Default is 50_000 + for idx in (10_000..=50_000).step_by(10_000) { + let code_with_loops = format!("LOOPS = {}\n{}", idx, PYSTONE); + let code_str = code_with_loops.as_str(); + + group.throughput(Throughput::Elements(idx as u64)); + group.bench_function(BenchmarkId::new("cpython", idx), |b| bench_cpython(b, black_box(code_str))); + group.bench_function(BenchmarkId::new("rustpython", idx), |b| bench_rustpy(b, "pystone", black_box(code_str))); + } + group.finish(); +} + +pub fn criterion_benchmark(c: &mut Criterion) { + benchmark_pystone(c); + benchmark_file(c, "nbody.py", NBODY); + benchmark_file(c, "mandlebrot.py", MANDELBROT); + benchmark_file(c, "pystone.py", PYSTONE); + benchmark_file(c, "strings.py", PYSTONE); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/parsing.rs b/benches/parsing.rs new file mode 100644 index 000000000..4a613eb99 --- /dev/null +++ b/benches/parsing.rs @@ -0,0 +1,45 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; +use rustpython_parser::lexer::{make_tokenizer, Tok}; +use rustpython_parser::parser::parse_program; + +const MINIDOM: &str = include_str!("./benchmarks/minidom.py"); + +pub fn criterion_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("tokenization"); + group.throughput(Throughput::Bytes(MINIDOM.len() as u64)); + group.bench_function("tokenization", |b| { + b.iter(|| { + let lexer = make_tokenizer(black_box(MINIDOM)); + for res in lexer { + let _token: Tok = res.unwrap().1; + } + }) + }); + group.finish(); + + let mut group = c.benchmark_group("parse_to_ast"); + group.throughput(Throughput::Bytes(MINIDOM.len() as u64)); + group.bench_function("rustpy", |b| { + b.iter(|| parse_program(black_box(MINIDOM)).unwrap()) + }); + group.bench_function("cpython", |b| { + let gil = cpython::Python::acquire_gil(); + let python = gil.python(); + + let globals = None; + let locals = cpython::PyDict::new(python); + + locals.set_item(python, "SOURCE_CODE", MINIDOM).unwrap(); + + let code = "compile(SOURCE_CODE, mode=\"exec\", filename=\"minidom.py\")"; + b.iter(|| { + let res: cpython::PyResult = + python.eval(black_box(code), globals, Some(&locals)); + assert!(res.is_ok()); + }) + }); + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benchmarks/test_benchmarks.py b/benches/test_benchmarks.py similarity index 100% rename from benchmarks/test_benchmarks.py rename to benches/test_benchmarks.py diff --git a/benchmarks/README.md b/benchmarks/README.md deleted file mode 100644 index dfb6bcb0b..000000000 --- a/benchmarks/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Benchmarking - -These are some files to determine performance of rustpython. - -## Usage - -Install pytest and pytest-benchmark: - - $ pip install pytest-benchmark - -Then run: - - $ pytest - -You can also benchmark the Rust benchmarks by just running -`cargo +nightly bench` from the root of the repository. Make sure you have Rust -nightly installed, as the benchmarking parts of the standard library are still -unstable. - -## Benchmark source - -- https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-python3-2.html diff --git a/benchmarks/bench.rs b/benchmarks/bench.rs deleted file mode 100644 index 786f5388a..000000000 --- a/benchmarks/bench.rs +++ /dev/null @@ -1,118 +0,0 @@ -#![feature(test)] - -extern crate test; - -use test::Bencher; - -use rustpython_compiler::compile; -use rustpython_vm::pyobject::PyResult; -use rustpython_vm::Interpreter; - -const MINIDOM: &str = include_str!("./benchmarks/minidom.py"); -const NBODY: &str = include_str!("./benchmarks/nbody.py"); -const MANDELBROT: &str = include_str!("./benchmarks/mandelbrot.py"); -const PYSTONE: &str = include_str!("./benchmarks/pystone.py"); - -#[bench] -fn bench_tokenization(b: &mut Bencher) { - use rustpython_parser::lexer::{make_tokenizer, Tok}; - - let source = MINIDOM; - - b.bytes = source.len() as _; - b.iter(|| { - let lexer = make_tokenizer(source); - for res in lexer { - let _token: Tok = res.unwrap().1; - } - }) -} - -#[bench] -fn bench_rustpy_parse_to_ast(b: &mut Bencher) { - use rustpython_parser::parser::parse_program; - - let source = MINIDOM; - - b.bytes = source.len() as _; - b.iter(|| parse_program(source).unwrap()) -} - -#[bench] -fn bench_cpython_parse_to_ast(b: &mut Bencher) { - let source = MINIDOM; - - let gil = cpython::Python::acquire_gil(); - let python = gil.python(); - - let globals = None; - let locals = cpython::PyDict::new(python); - - locals.set_item(python, "SOURCE_CODE", source).unwrap(); - - let code = "compile(SOURCE_CODE, mode=\"exec\", filename=\"minidom.py\")"; - - b.bytes = source.len() as _; - b.iter(|| { - let res: cpython::PyResult = python.eval(code, globals, Some(&locals)); - assert!(res.is_ok()); - }) -} - -fn bench_cpython(b: &mut Bencher, source: &str) { - let gil = cpython::Python::acquire_gil(); - let python = gil.python(); - - let globals = None; - let locals = None; - - b.iter(|| { - let res: cpython::PyResult<()> = python.run(source, globals, locals); - assert!(res.is_ok()); - }) -} - -#[bench] -fn bench_cpython_nbody(b: &mut Bencher) { - bench_cpython(b, NBODY) -} - -#[bench] -fn bench_cpython_mandelbrot(b: &mut Bencher) { - bench_cpython(b, MANDELBROT) -} - -#[bench] -fn bench_cpython_pystone(b: &mut Bencher) { - bench_cpython(b, PYSTONE) -} - -fn bench_rustpy(b: &mut Bencher, name: &str, source: &str) { - // NOTE: Take long time. - Interpreter::default().enter(|vm| { - let code = vm - .compile(source, compile::Mode::Exec, name.to_owned()) - .unwrap(); - - b.iter(|| { - let scope = vm.new_scope_with_builtins(); - let res: PyResult = vm.run_code_obj(code.clone(), scope); - vm.unwrap_pyresult(res); - }) - }) -} - -#[bench] -fn bench_rustpy_nbody(b: &mut Bencher) { - bench_rustpy(b, "nbody.py", NBODY) -} - -#[bench] -fn bench_rustpy_mandelbrot(b: &mut Bencher) { - bench_rustpy(b, "mandelbrot.py", MANDELBROT) -} - -#[bench] -fn bench_rustpy_pystone(b: &mut Bencher) { - bench_rustpy(b, "pystone.py", PYSTONE) -}