mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Refactor benchmarking suite to use Criterion
This commit is contained in:
14 files changed
+370
-198
No files matched your search
@@ -16,3 +16,4 @@ flame.txt
|
||||
flamescope.json
|
||||
/wapm.lock
|
||||
/wapm_packages
|
||||
/.cargo/config
|
||||
Generated
+185
@@ -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"
|
||||
|
||||
+13
-4
@@ -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]
|
||||
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
@@ -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))
|
||||
@@ -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)
|
||||
File renamed without changes.
@@ -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);
|
||||
@@ -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<cpython::PyObject> =
|
||||
python.eval(black_box(code), globals, Some(&locals));
|
||||
assert!(res.is_ok());
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
criterion_main!(benches);
|
||||
File renamed without changes.
@@ -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
|
||||
@@ -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<cpython::PyObject> = 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)
|
||||
}
|
||||
Reference in new issue
Block a user