-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[red-knot] Add very basic benchmark (#12182)
- Loading branch information
1 parent
497fd4c
commit e2e0889
Showing
7 changed files
with
197 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
#![allow(clippy::disallowed_names)] | ||
|
||
use red_knot::program::Program; | ||
use red_knot::Workspace; | ||
use red_knot_module_resolver::{set_module_resolution_settings, ModuleResolutionSettings}; | ||
use ruff_benchmark::criterion::{ | ||
criterion_group, criterion_main, BatchSize, Criterion, Throughput, | ||
}; | ||
use ruff_db::file_system::{FileSystemPath, MemoryFileSystem}; | ||
use ruff_db::parsed::parsed_module; | ||
use ruff_db::vfs::{system_path_to_file, VfsFile}; | ||
use ruff_db::Upcast; | ||
|
||
static FOO_CODE: &str = r#" | ||
import typing | ||
from bar import Bar | ||
class Foo(Bar): | ||
def foo() -> str: | ||
return "foo" | ||
@typing.override | ||
def bar() -> str: | ||
return "foo_bar" | ||
"#; | ||
|
||
static BAR_CODE: &str = r#" | ||
class Bar: | ||
def bar() -> str: | ||
return "bar" | ||
def random(arg: int) -> int: | ||
if arg == 1: | ||
return 48472783 | ||
if arg < 10: | ||
return 20 | ||
return 36673 | ||
"#; | ||
|
||
static TYPING_CODE: &str = r#" | ||
def override(): ... | ||
"#; | ||
|
||
struct Case { | ||
program: Program, | ||
fs: MemoryFileSystem, | ||
foo: VfsFile, | ||
bar: VfsFile, | ||
typing: VfsFile, | ||
} | ||
|
||
fn setup_case() -> Case { | ||
let fs = MemoryFileSystem::new(); | ||
let foo_path = FileSystemPath::new("/src/foo.py"); | ||
let bar_path = FileSystemPath::new("/src/bar.py"); | ||
let typing_path = FileSystemPath::new("/src/typing.pyi"); | ||
fs.write_files([ | ||
(foo_path, FOO_CODE), | ||
(bar_path, BAR_CODE), | ||
(typing_path, TYPING_CODE), | ||
]) | ||
.unwrap(); | ||
|
||
let workspace_root = FileSystemPath::new("/src"); | ||
let workspace = Workspace::new(workspace_root.to_path_buf()); | ||
|
||
let mut program = Program::new(workspace, fs.clone()); | ||
let foo = system_path_to_file(&program, foo_path).unwrap(); | ||
|
||
set_module_resolution_settings( | ||
&mut program, | ||
ModuleResolutionSettings { | ||
extra_paths: vec![], | ||
workspace_root: workspace_root.to_path_buf(), | ||
site_packages: None, | ||
custom_typeshed: None, | ||
}, | ||
); | ||
|
||
program.workspace_mut().open_file(foo); | ||
|
||
let bar = system_path_to_file(&program, bar_path).unwrap(); | ||
let typing = system_path_to_file(&program, typing_path).unwrap(); | ||
|
||
Case { | ||
program, | ||
fs, | ||
foo, | ||
bar, | ||
typing, | ||
} | ||
} | ||
|
||
fn benchmark_without_parse(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("red_knot/check_file"); | ||
group.throughput(Throughput::Bytes(FOO_CODE.len() as u64)); | ||
|
||
group.bench_function("red_knot_check_file[without_parse]", |b| { | ||
b.iter_batched( | ||
|| { | ||
let case = setup_case(); | ||
// Pre-parse the module to only measure the semantic time. | ||
parsed_module(case.program.upcast(), case.foo); | ||
parsed_module(case.program.upcast(), case.bar); | ||
parsed_module(case.program.upcast(), case.typing); | ||
case | ||
}, | ||
|case| { | ||
let Case { program, foo, .. } = case; | ||
let result = program.check_file(foo).unwrap(); | ||
|
||
assert_eq!(result.as_slice(), [] as [String; 0]); | ||
}, | ||
BatchSize::SmallInput, | ||
); | ||
}); | ||
|
||
group.finish(); | ||
} | ||
|
||
fn benchmark_incremental(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("red_knot/check_file"); | ||
group.throughput(Throughput::Bytes(FOO_CODE.len() as u64)); | ||
|
||
group.bench_function("red_knot_check_file[incremental]", |b| { | ||
b.iter_batched( | ||
|| { | ||
let mut case = setup_case(); | ||
case.program.check_file(case.foo).unwrap(); | ||
|
||
case.fs | ||
.write_file( | ||
FileSystemPath::new("/src/foo.py"), | ||
format!("{BAR_CODE}\n# A comment\n"), | ||
) | ||
.unwrap(); | ||
|
||
case.bar.touch(&mut case.program); | ||
case | ||
}, | ||
|case| { | ||
let Case { program, foo, .. } = case; | ||
let result = program.check_file(foo).unwrap(); | ||
|
||
assert_eq!(result.as_slice(), [] as [String; 0]); | ||
}, | ||
BatchSize::SmallInput, | ||
); | ||
}); | ||
|
||
group.finish(); | ||
} | ||
|
||
fn benchmark_cold(criterion: &mut Criterion) { | ||
let mut group = criterion.benchmark_group("red_knot/check_file"); | ||
group.throughput(Throughput::Bytes(FOO_CODE.len() as u64)); | ||
|
||
group.bench_function("red_knot_check_file[cold]", |b| { | ||
b.iter_batched( | ||
setup_case, | ||
|case| { | ||
let Case { program, foo, .. } = case; | ||
let result = program.check_file(foo).unwrap(); | ||
|
||
assert_eq!(result.as_slice(), [] as [String; 0]); | ||
}, | ||
BatchSize::SmallInput, | ||
); | ||
}); | ||
|
||
group.finish(); | ||
} | ||
|
||
criterion_group!(cold, benchmark_without_parse); | ||
criterion_group!(without_parse, benchmark_cold); | ||
criterion_group!(incremental, benchmark_incremental); | ||
criterion_main!(without_parse, cold, incremental); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters