use criterion::{black_box, criterion_group, criterion_main, Criterion};
use indoc::indoc;
use mpatch::{apply_patch_to_content, parse_diffs, ApplyOptions, Patch};
fn parsing_benches(c: &mut Criterion) {
let mut group = c.benchmark_group("Parsing");
let simple_diff = indoc! {r#"
A markdown file with some text.
```diff
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,3 @@
fn main() {
- println!("Hello, world!");
+ println!("Hello, mpatch!");
}
```
"#};
group.bench_function("simple_diff", |b| {
b.iter(|| parse_diffs(black_box(simple_diff)).unwrap())
});
let multi_file_diff = indoc! {r#"
```diff
--- a/file1.txt
+++ b/file1.txt
@@ -1 +1 @@
-foo
+bar
--- a/file2.txt
+++ b/file2.txt
@@ -1 +1 @@
-baz
+qux
```
"#};
group.bench_function("multi_file_diff", |b| {
b.iter(|| parse_diffs(black_box(multi_file_diff)).unwrap())
});
let mut large_diff_content =
"```diff\n--- a/large_file.txt\n+++ b/large_file.txt\n".to_string();
for i in 0..100 {
large_diff_content.push_str(&format!(
"@@ -{},3 +{},3 @@\n context line {}\n-old line {}\n+new line {}\n",
i * 5 + 1,
i * 5 + 1,
i,
i,
i
));
}
large_diff_content.push_str("```");
group.bench_function("large_diff_100_hunks", |b| {
b.iter(|| parse_diffs(black_box(&large_diff_content)).unwrap())
});
let mut large_markdown = "Lorem ipsum dolor sit amet...\n".repeat(1000);
large_markdown.push_str(simple_diff);
group.bench_function("large_markdown_scan", |b| {
b.iter(|| parse_diffs(black_box(&large_markdown)).unwrap())
});
group.finish();
}
struct ApplyBenchSetup {
patch: Patch,
initial_content: String,
}
fn applying_benches(c: &mut Criterion) {
let mut group = c.benchmark_group("Applying");
let options_exact = ApplyOptions::exact();
let options_fuzzy = ApplyOptions::new();
let creation_setup = ApplyBenchSetup {
patch: parse_diffs(indoc! {r#"
```diff
--- a/new_file.txt
+++ b/new_file.txt
@@ -0,0 +1,2 @@
+Hello
+New World
```
"#})
.unwrap()
.remove(0),
initial_content: String::new(), };
group.bench_function("file_creation", |b| {
b.iter(|| {
criterion::black_box(apply_patch_to_content(
black_box(&creation_setup.patch),
black_box(None),
&options_exact,
));
});
});
let mut large_file_content = String::new();
for i in 0..10000 {
large_file_content.push_str(&format!("This is line number {}\n", i));
}
let exact_large_setup = ApplyBenchSetup {
patch: parse_diffs(indoc! {r#"
```diff
--- a/large_file.txt
+++ b/large_file.txt
@@ -5000,5 +5000,5 @@
This is line number 4999
This is line number 5000
-This is line number 5001
+THIS LINE WAS CHANGED
This is line number 5002
This is line number 5003
```
"#})
.unwrap()
.remove(0),
initial_content: large_file_content,
};
group.bench_function("exact_match_large_file", |b| {
b.iter(|| {
criterion::black_box(apply_patch_to_content(
black_box(&exact_large_setup.patch),
black_box(Some(&exact_large_setup.initial_content)),
&options_exact,
));
});
});
let mut fuzzy_target_content = exact_large_setup.initial_content.clone();
fuzzy_target_content.insert_str(100, "An extra line to break exact match\n");
let fuzzy_anchor_setup = ApplyBenchSetup {
patch: exact_large_setup.patch.clone(), initial_content: fuzzy_target_content,
};
group.bench_function("fuzzy_match_large_file_with_anchor", |b| {
b.iter(|| {
criterion::black_box(apply_patch_to_content(
black_box(&fuzzy_anchor_setup.patch),
black_box(Some(&fuzzy_anchor_setup.initial_content)),
&options_fuzzy,
));
});
});
let repetitive_content = "println!(\"hello world\");\n".repeat(10000);
let worst_case_setup = ApplyBenchSetup {
patch: parse_diffs(indoc! {r#"
```diff
--- a/repetitive.txt
+++ b/repetitive.txt
@@ -5000,5 +5000,5 @@
This is a unique context line 1
-This is a unique line to be removed
+This is a unique line to be added
This is a unique context line 2
```
"#})
.unwrap()
.remove(0),
initial_content: repetitive_content,
};
group.bench_function("fuzzy_match_worst_case_no_anchor", |b| {
b.iter(|| {
criterion::black_box(apply_patch_to_content(
black_box(&worst_case_setup.patch),
black_box(Some(&worst_case_setup.initial_content)),
&options_fuzzy,
));
});
});
let ambiguous_content = indoc! {"
// Block 1
fn duplicate() {
println!(\"hello\");
}
// ...
// Block 2
fn duplicate() {
println!(\"hello\");
}
"}
.repeat(100);
let ambiguous_setup = ApplyBenchSetup {
patch: parse_diffs(indoc! {r#"
```diff
--- a/ambiguous.txt
+++ b/ambiguous.txt
@@ -7,3 +7,3 @@
fn duplicate() {
- println!("hello");
+ println!("world");
}
```
"#})
.unwrap()
.remove(0),
initial_content: ambiguous_content,
};
group.bench_function("ambiguous_exact_match_resolved_by_hint", |b| {
b.iter(|| {
criterion::black_box(apply_patch_to_content(
black_box(&ambiguous_setup.patch),
black_box(Some(&ambiguous_setup.initial_content)),
&options_exact,
));
});
});
group.finish();
}
criterion_group!(benches, parsing_benches, applying_benches);
criterion_main!(benches);