Add benchmarking

This commit is contained in:
Charles Marsh 2022-08-19 13:19:00 -04:00
parent 623152768e
commit 12197216c9
5 changed files with 92 additions and 2 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
# Local cache # Local cache
.cache .cache
resources/test
!resources/test/src
### ###
# Rust.gitignore # Rust.gitignore

1
Cargo.lock generated
View File

@ -1529,6 +1529,7 @@ dependencies = [
"clearscreen", "clearscreen",
"colored", "colored",
"fern", "fern",
"lazy_static",
"log", "log",
"notify", "notify",
"pyo3", "pyo3",

View File

@ -16,6 +16,7 @@ clap = { version = "3.2.16", features = ["derive"] }
clearscreen = { version = "1.0.10" } clearscreen = { version = "1.0.10" }
colored = { version = "2.0.0" } colored = { version = "2.0.0" }
fern = { version = "0.6.1" } fern = { version = "0.6.1" }
lazy_static = { version = "1.4.0" }
log = { version = "0.4.17" } log = { version = "0.4.17" }
notify = { version = "4.0.17" } notify = { version = "4.0.17" }
pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37"] } pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37"] }
@ -25,3 +26,7 @@ rustpython-parser = { git = "https://github.com/RustPython/RustPython.git", rev
serde = { version = "1.0.143", features = ["derive"] } serde = { version = "1.0.143", features = ["derive"] }
serde_json = { version = "1.0.83" } serde_json = { version = "1.0.83" }
walkdir = { version = "2.3.2" } walkdir = { version = "2.3.2" }
[profile.release]
lto = true
panic = "abort"

View File

@ -55,3 +55,31 @@ cargo run resources/test/src
maturin publish --skip-existing --target x86_64-apple-darwin maturin publish --skip-existing --target x86_64-apple-darwin
maturin publish --skip-existing --target aarch64-apple-darwin maturin publish --skip-existing --target aarch64-apple-darwin
``` ```
## Benchmarking
First, clone [CPython](https://github.com/python/cpython). It's a large and diverse Python codebase,
which makes it a good target for benchmarking. Note that we clone v3.9, as `RustPython` doesn't yet
support pattern matching, which was introduced in v3.10.
```shell
git clone --branch 3.9 https://github.com/python/cpython.git resources/test/cpython
```
Next, to benchmark the release build:
```shell
cargo build --release
hyperfine --warmup 5 \
"./target/release/rust_python_linter ./resources/test/cpython/ --no-cache" \
"./target/release/rust_python_linter ./resources/test/cpython/"
Benchmark 1: ./target/release/rust_python_linter ./resources/test/cpython/ --no-cache
Time (mean ± σ): 353.6 ms ± 7.6 ms [User: 2868.8 ms, System: 171.5 ms]
Range (min … max): 344.4 ms … 367.3 ms 10 runs
Benchmark 2: ./target/release/rust_python_linter ./resources/test/cpython/
Time (mean ± σ): 59.6 ms ± 2.5 ms [User: 36.4 ms, System: 345.6 ms]
Range (min … max): 55.9 ms … 67.0 ms 48 runs
```

View File

@ -1,10 +1,63 @@
use anyhow::Result;
use lazy_static::lazy_static;
use std::collections::HashSet;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read}; use std::io::{BufRead, BufReader, Read};
use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use anyhow::Result;
use walkdir::{DirEntry, WalkDir}; use walkdir::{DirEntry, WalkDir};
lazy_static! {
// TODO(charlie): Make these configurable.
static ref EXCLUDES: HashSet<&'static str> = vec![
"resources/test/cpython/Lib/ctypes/test/test_numbers.py",
"resources/test/cpython/Lib/dataclasses.py",
"resources/test/cpython/Lib/lib2to3/tests/data/bom.py",
"resources/test/cpython/Lib/lib2to3/tests/data/crlf.py",
"resources/test/cpython/Lib/lib2to3/tests/data/different_encoding.py",
"resources/test/cpython/Lib/lib2to3/tests/data/false_encoding.py",
"resources/test/cpython/Lib/lib2to3/tests/data/py2_test_grammar.py",
"resources/test/cpython/Lib/sqlite3/test/factory.py",
"resources/test/cpython/Lib/sqlite3/test/hooks.py",
"resources/test/cpython/Lib/sqlite3/test/regression.py",
"resources/test/cpython/Lib/sqlite3/test/transactions.py",
"resources/test/cpython/Lib/sqlite3/test/types.py",
"resources/test/cpython/Lib/test/bad_coding2.py",
"resources/test/cpython/Lib/test/badsyntax_3131.py",
"resources/test/cpython/Lib/test/badsyntax_pep3120.py",
"resources/test/cpython/Lib/test/encoded_modules/module_iso_8859_1.py",
"resources/test/cpython/Lib/test/encoded_modules/module_koi8_r.py",
"resources/test/cpython/Lib/test/sortperf.py",
"resources/test/cpython/Lib/test/test_email/torture_test.py",
"resources/test/cpython/Lib/test/test_fstring.py",
"resources/test/cpython/Lib/test/test_genericpath.py",
"resources/test/cpython/Lib/test/test_getopt.py",
"resources/test/cpython/Lib/test/test_htmlparser.py",
"resources/test/cpython/Lib/test/test_importlib/stubs.py",
"resources/test/cpython/Lib/test/test_importlib/test_files.py",
"resources/test/cpython/Lib/test/test_importlib/test_metadata_api.py",
"resources/test/cpython/Lib/test/test_importlib/test_open.py",
"resources/test/cpython/Lib/test/test_importlib/test_util.py",
"resources/test/cpython/Lib/test/test_named_expressions.py",
"resources/test/cpython/Lib/test/test_peg_generator/__main__.py",
"resources/test/cpython/Lib/test/test_pipes.py",
"resources/test/cpython/Lib/test/test_source_encoding.py",
"resources/test/cpython/Lib/test/test_weakref.py",
"resources/test/cpython/Lib/test/test_webbrowser.py",
"resources/test/cpython/Lib/tkinter/__main__.py",
"resources/test/cpython/Lib/tkinter/test/test_tkinter/test_variables.py",
"resources/test/cpython/Modules/_decimal/libmpdec/literature/fnt.py",
"resources/test/cpython/Modules/_decimal/tests/deccheck.py",
"resources/test/cpython/Tools/i18n/pygettext.py",
"resources/test/cpython/Tools/test2to3/maintest.py",
"resources/test/cpython/Tools/test2to3/setup.py",
"resources/test/cpython/Tools/test2to3/test/test_foo.py",
"resources/test/cpython/Tools/test2to3/test2to3/hello.py",
]
.into_iter()
.collect();
}
fn is_not_hidden(entry: &DirEntry) -> bool { fn is_not_hidden(entry: &DirEntry) -> bool {
entry entry
.file_name() .file_name()
@ -20,6 +73,7 @@ pub fn iter_python_files(path: &PathBuf) -> impl Iterator<Item = DirEntry> {
.filter_entry(is_not_hidden) .filter_entry(is_not_hidden)
.filter_map(|entry| entry.ok()) .filter_map(|entry| entry.ok())
.filter(|entry| entry.path().to_string_lossy().ends_with(".py")) .filter(|entry| entry.path().to_string_lossy().ends_with(".py"))
.filter(|entry| !EXCLUDES.contains(entry.path().to_string_lossy().deref()))
} }
pub fn read_line(path: &Path, row: &usize) -> Result<String> { pub fn read_line(path: &Path, row: &usize) -> Result<String> {