Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: compare micro benchmarks #762

Merged
merged 153 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
153 commits
Select commit Hold shift + click to select a range
3a76ee1
Create a.md
alankritdabral Dec 19, 2023
38fa9ed
Update bot.yml
alankritdabral Dec 19, 2023
f2461b0
Update bot.yml
alankritdabral Dec 19, 2023
818da12
Update bot.yml
alankritdabral Dec 19, 2023
3fbb433
Update bot.yml
alankritdabral Dec 19, 2023
9339ec5
Update bot.yml
alankritdabral Dec 19, 2023
f24b50a
Rename a.md to benches/a.md
alankritdabral Dec 19, 2023
be4f570
Update bot.yml
alankritdabral Dec 19, 2023
c611579
Update bot.yml
alankritdabral Dec 19, 2023
c36f715
Update bot.yml
alankritdabral Dec 19, 2023
d84a5ad
Update bot.yml
alankritdabral Dec 19, 2023
8fd7c15
Criterion compare
Dec 18, 2023
e08acb2
Instructions to run benchmarks locally
Dec 18, 2023
731c0fc
Update .github/workflows/bot.yml
amitksingh1490 Dec 19, 2023
074f6a5
Update bot.yml
alankritdabral Dec 19, 2023
b928f7a
run benchmarks on main in Cache_Benchmarks
Dec 19, 2023
f4c3da7
fail ci on positive percentage change > 1
Dec 19, 2023
4fa942b
Update bot.yml
alankritdabral Dec 19, 2023
debfd02
Update bot.yml
alankritdabral Dec 19, 2023
2015d5f
Update bot.yml
alankritdabral Dec 19, 2023
5f85a5a
Update bot.yml
alankritdabral Dec 19, 2023
c2701a9
Update bot.yml
alankritdabral Dec 19, 2023
9380c0b
Update bot.yml
alankritdabral Dec 19, 2023
be51bcb
Update bot.yml
alankritdabral Dec 19, 2023
112e21e
comment on pr
Dec 19, 2023
c8e1466
added function to add output file in script
Dec 19, 2023
8fff13c
fixes
Dec 19, 2023
4ddc098
added option in(parse_json_benchmark) output file
Dec 19, 2023
fd9bd2f
Merge branch 'tailcallhq:main' into main
alankritdabral Dec 19, 2023
b0ae40e
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 20, 2023
d914044
Update bot.yml
alankritdabral Dec 20, 2023
cf890eb
Merge branch 'main' into hello-world
alankritdabral Dec 20, 2023
37e99c0
Update bot.yml
alankritdabral Dec 20, 2023
75ea46e
Update bot.yml
alankritdabral Dec 20, 2023
5860ff7
Update bot.yml
alankritdabral Dec 20, 2023
43cfeb8
Update bot.yml
alankritdabral Dec 20, 2023
9444e3f
Update bot.yml
alankritdabral Dec 20, 2023
177d047
Update bot.yml
alankritdabral Dec 20, 2023
710d439
Update bot.yml
alankritdabral Dec 20, 2023
fa410c1
Update bot.yml
alankritdabral Dec 20, 2023
51c8b27
Update bot.yml
alankritdabral Dec 20, 2023
8467c44
Update bot.yml
alankritdabral Dec 20, 2023
f76d0fa
Update bot.yml
alankritdabral Dec 20, 2023
e5be51c
Update bot.yml
alankritdabral Dec 20, 2023
dab599c
Update bot.yml
alankritdabral Dec 20, 2023
b9a521a
Merge branch 'main' into hello-world
alankritdabral Dec 20, 2023
c779fb9
Update bot.yml
alankritdabral Dec 20, 2023
2ed3171
Update bot.yml
alankritdabral Dec 20, 2023
87d6979
Update bot.yml
alankritdabral Dec 20, 2023
92ebcb4
samll changes
Dec 20, 2023
92901e8
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 20, 2023
66780e7
llinting
Dec 20, 2023
ccd2c17
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 20, 2023
7614427
Removed comment on pr
Dec 21, 2023
88ef3f2
samll changes
Dec 21, 2023
89baebd
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 21, 2023
0e38ceb
Update parse_json_benchmark.rs
alankritdabral Dec 21, 2023
0a051e0
added check table in script criterion_compare
Dec 21, 2023
c962c93
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 21, 2023
5cf626e
Update bot.yml
alankritdabral Dec 21, 2023
638c77a
Update .github/workflows/bot.yml
alankritdabral Dec 21, 2023
88162d7
Update .github/contributing.md
alankritdabral Dec 21, 2023
63aff97
Update bot.yml
alankritdabral Dec 21, 2023
4e0f47d
Update bot.yml
alankritdabral Dec 21, 2023
77d0d8d
Update bot.yml
alankritdabral Dec 21, 2023
9bbe6a6
Update bot.yml
alankritdabral Dec 21, 2023
4453906
Update bot.yml
alankritdabral Dec 21, 2023
3a8e8d0
Update .github/workflows/bot.yml
alankritdabral Dec 21, 2023
c772d74
suggestions
Dec 21, 2023
2cf72cf
linting
Dec 21, 2023
90e9a97
fail on no cache found
Dec 21, 2023
fa6d1e9
linting issues
Dec 21, 2023
bfc8a0c
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 21, 2023
312ff35
Update bot.yml
alankritdabral Dec 21, 2023
ca23838
Update bot.yml
alankritdabral Dec 21, 2023
cb7e280
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 22, 2023
b92bc27
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 23, 2023
5d6caff
changed degradation from 1 to 10
Dec 24, 2023
8e0e16c
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 24, 2023
5117ab8
Update bot.yml
alankritdabral Dec 24, 2023
b8e2d67
Update bot.yml
alankritdabral Dec 24, 2023
28b610d
Merge pull request #60 from alankritdabral/compare-benchmarks
alankritdabral Dec 24, 2023
9d7318b
Update bot.yml
alankritdabral Dec 24, 2023
5a4b4af
Merge branch 'main' into hello-world
alankritdabral Dec 24, 2023
ba438c7
Update bot.yml
alankritdabral Dec 24, 2023
c542e8d
Update bot.yml
alankritdabral Dec 24, 2023
5671682
Update bot.yml
alankritdabral Dec 24, 2023
b873458
Update bot.yml
alankritdabral Dec 24, 2023
578f28b
Update bot.yml
alankritdabral Dec 24, 2023
a74ccba
Update bot.yml
alankritdabral Dec 24, 2023
a3a941c
Update bot.yml
alankritdabral Dec 24, 2023
d7be1cc
Update bot.yml
alankritdabral Dec 24, 2023
6dcad70
Update bot.yml
alankritdabral Dec 24, 2023
f8d0fc9
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 24, 2023
8fa4cb8
Update bot.yml
alankritdabral Dec 25, 2023
1c166f2
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 25, 2023
679022c
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 25, 2023
f9d123e
Update bot.yml
alankritdabral Dec 25, 2023
3bc68ed
Update bot.yml
alankritdabral Dec 25, 2023
3214615
Update bot.yml
alankritdabral Dec 25, 2023
ed5bace
Update bot.yml
alankritdabral Dec 25, 2023
e96031f
Update bot.yml
alankritdabral Dec 25, 2023
d0257d2
Update bot.yml
alankritdabral Dec 25, 2023
67da835
Update bot.yml
alankritdabral Dec 25, 2023
6375290
Update bot.yml
alankritdabral Dec 25, 2023
2e6eabd
Update bot.yml
alankritdabral Dec 25, 2023
2595876
Merge branch 'main' into hello-world
alankritdabral Dec 25, 2023
83bf95f
Update bot.yml
alankritdabral Dec 25, 2023
b03f262
Update bot.yml
alankritdabral Dec 25, 2023
9d7f9bb
Update bot.yml
alankritdabral Dec 25, 2023
5efd389
Update bot.yml
alankritdabral Dec 25, 2023
7b81e13
Update bot.yml
alankritdabral Dec 25, 2023
566b06b
Update bot.yml
alankritdabral Dec 25, 2023
b126920
Update bot.yml
alankritdabral Dec 25, 2023
f757ec6
Update bot.yml
alankritdabral Dec 25, 2023
eb18bb3
Update bot.yml
alankritdabral Dec 25, 2023
31c8615
Update bot.yml
alankritdabral Dec 25, 2023
5db41c8
Update bot.yml
alankritdabral Dec 25, 2023
d3b1cd0
Update bot.yml
alankritdabral Dec 25, 2023
d544f0e
Update bot.yml
alankritdabral Dec 25, 2023
851f187
Merge branch 'main' into hello-world
alankritdabral Dec 25, 2023
423ddee
Update bot.yml
alankritdabral Dec 25, 2023
34515da
Update bot.yml
alankritdabral Dec 25, 2023
ab9084d
Update bot.yml
alankritdabral Dec 25, 2023
4d68ef5
Update bot.yml
alankritdabral Dec 25, 2023
e5a4e69
Merge pull request #62 from alankritdabral/hello-world
alankritdabral Dec 25, 2023
8ae0cb5
Update bot.yml
alankritdabral Dec 25, 2023
86c55bc
Update bot.yml
alankritdabral Dec 25, 2023
47f72c5
Update bot.yml
alankritdabral Dec 25, 2023
db45a2d
Merge pull request #64 from alankritdabral/hello-world
alankritdabral Dec 25, 2023
324d442
Update bot.yml
alankritdabral Dec 25, 2023
1e733aa
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 25, 2023
28a8a9c
Update bot.yml
alankritdabral Dec 25, 2023
f2e2fe0
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 25, 2023
21491a9
Delete benches/a.md
alankritdabral Dec 25, 2023
df87b85
linting fix
Dec 25, 2023
9a08c44
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 26, 2023
75075a1
linting
Dec 26, 2023
ceb6ef3
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 27, 2023
6501a6d
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 27, 2023
16fd5fd
changes to src
Dec 27, 2023
e57e449
fixes
Dec 27, 2023
53df26f
Merge branch 'main' into compare-benchmarks
alankritdabral Dec 27, 2023
fd8749b
Merge branch 'main' into compare-benchmarks
tusharmath Dec 28, 2023
b30fbfe
chore: update scripts
tusharmath Dec 28, 2023
ddcbf61
update scripts
tusharmath Dec 28, 2023
3794b48
Update bot.yml
alankritdabral Dec 28, 2023
0a41e93
update script paths
tusharmath Dec 28, 2023
b778032
removed Nginx
Dec 28, 2023
f795a64
fixes
Dec 28, 2023
1804bdc
update bot.yml
tusharmath Dec 28, 2023
82cff73
update bot.yml
tusharmath Dec 28, 2023
f52df28
Update criterion_compare.rs
alankritdabral Dec 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ Thank you for considering contributing to **Tailcall**! This document outlines t
cargo test
```

## Benchmarks Comparison

### Criterion Benchmarks

1. **Important:** Make sure all the commits are done.
2. **Install packages:** Install cargo-criterion rust-script.
```bash
cargo install cargo-criterion rust-script
```
3. **Comparing Benchmarks:**
You need to follow the following steps to compare benchmarks between `main`(Baseline) and your branch.

```bash
git checkout main
cargo criterion --message-format=json > benches/main_benchmarks.json
git checkout -
cargo criterion --message-format=json > benches/benchmarks.json
rust-script benches/criterion_compare benches/main_benchmarks.json benches/benchmarks.json

```

4. **Check the Results:** If the benchmarks show more than 10% degradation, the script will exit with an error. Please check "benches/benchmark.md" file to identify the benchmarks that failed and investigate the code changes that might have caused the degradation.
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved

## Documentation

1. **Update README:** If your changes necessitate a change in the way users interact with the application, update the README accordingly.
Expand Down
48 changes: 46 additions & 2 deletions .github/workflows/bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,12 @@ jobs:
Cache_Benchmarks:
name: Micro Benchmarks
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
tusharmath marked this conversation as resolved.
Show resolved Hide resolved
steps:
- name: Check out code
uses: actions/checkout@v4
uses: actions/checkout@v2
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved

- name: Install Rust
uses: actions-rs/toolchain@v1
Expand All @@ -174,7 +177,8 @@ jobs:
run: |
cargo install cargo-criterion rust-script
cargo criterion --message-format=json > benches/main_benchmarks.json
rust-script benches/parse_json_benchmark benches/main_benchmarks.json
rust-script benches/parse_json_benchmark benches/main_benchmarks.json benches/main_benchmarks.md
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved
cat benches/main_benchmarks.md

- name: Cache Criterion Benchmarks Json
uses: actions/cache@v2
Expand All @@ -183,3 +187,43 @@ jobs:
key: criterion_benchmarks_${{ github.sha }}
restore-keys: |
criterion_benchmarks_

Criterion_compare:
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved
name: Comparing Micro Benchmarks
if: contains(github.event.pull_request.labels.*.name, 'benchmark') || github.event_name == 'push'
runs-on: ubuntu-latest
amitksingh1490 marked this conversation as resolved.
Show resolved Hide resolved
permissions:
pull-requests: write
contents: write
steps:
- name: Check out code
uses: actions/checkout@v2

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true

- name: Restore file
uses: actions/cache@v2
with:
path: benches/main_benchmarks.json
key: criterion_benchmarks_${{ github.sha }}
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved
restore-keys: |
criterion_benchmarks_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is used to restore the cache file (main benchmarks in json )


- name: Print Criterion Benchmarks
run: |
cargo install cargo-criterion rust-script
cargo criterion --message-format=json > benches/benchmarks.json
rust-script benches/parse_json_benchmark benches/benchmarks.json benches/change_benchmarks.md
cat benches/change_benchmarks.md
alankritdabral marked this conversation as resolved.
Show resolved Hide resolved

- name: Compare Criterion Benchmarks
run: |
rust-script benches/criterion_compare benches/main_benchmarks.json benches/benchmarks.json table
cat benches/benchmark.md

- name: Check Degradation
run: rust-script benches/criterion_compare benches/main_benchmarks.json benches/benchmarks.json check
167 changes: 167 additions & 0 deletions benches/criterion_compare.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env cargo-script

//! ```cargo
//! [dependencies]
//! serde_json = "1.0"
//! serde = { version = "1", features = ["derive"] }
//! ```

use std::{env, fs};

use serde::Deserialize;
use serde_json::from_str;

#[derive(Debug, Deserialize)]
#[allow(dead_code)]
struct Benchmark {
id: String,
typical: Typical,
}

#[derive(Debug, Deserialize)]
#[allow(dead_code)]
struct Typical {
estimate: f64,
unit: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Get command-line arguments
let args: Vec<String> = env::args().collect();

// Check if two or three file paths are provided
if args.len() != 3 && args.len() != 4 {
eprintln!("Usage: {} <old_file_path> <new_file_path> [check | table]", args[0]);
std::process::exit(1);
}

// Extract file paths from command-line arguments
let old_file_path = &args[1];
let new_file_path = &args[2];

let old_content = fs::read_to_string(old_file_path)?;
let old_benchmarks: Vec<Benchmark> = old_content.lines().filter_map(|line| from_str(line).ok()).collect();

let new_content = fs::read_to_string(new_file_path)?;
let new_benchmarks: Vec<Benchmark> = new_content.lines().filter_map(|line| from_str(line).ok()).collect();

if old_benchmarks.len() != new_benchmarks.len() {
return Err("Mismatch in the number of benchmarks between old and new files".into());
}

// Specify the output file path for Markdown
let markdown_output_file_path = "benches/benchmark.md";

// Check the command-line argument
match args.get(3).map(|s| s.as_str()) {
Some("check") => {
perform_check(&old_benchmarks, &new_benchmarks)?;
}
Some("table") => {
// Generate the comparison table in markdown and write it to the output file
let comparison_table_markdown = generate_comparison_table_markdown(&old_benchmarks, &new_benchmarks)?;
fs::write(markdown_output_file_path, comparison_table_markdown)?;
generate_and_print_table(&old_benchmarks, &new_benchmarks)?;
}
None => {
// Generate the comparison table in markdown and write it to the output file
let comparison_table_markdown = generate_comparison_table_markdown(&old_benchmarks, &new_benchmarks)?;
fs::write(markdown_output_file_path, comparison_table_markdown)?;
generate_and_print_table(&old_benchmarks, &new_benchmarks)?;
perform_check(&old_benchmarks, &new_benchmarks)?;
}
Some(arg) => {
eprintln!(
"Error: Invalid argument '{}'. Please use 'check', 'table', or no argument.",
arg
);
std::process::exit(1);
}
}

Ok(())
}

fn perform_check(old_benchmarks: &[Benchmark], new_benchmarks: &[Benchmark]) -> Result<(), Box<dyn std::error::Error>> {
// Collect benchmarks exceeding the 1% change threshold
let benchmarks_exceeding_threshold: Vec<_> = old_benchmarks
.iter()
.zip(new_benchmarks.iter())
.filter_map(|(old, new)| {
let percentage_change = calculate_percentage_change(old.typical.estimate, new.typical.estimate);
if percentage_change > 1.0 {
Some((old.id.clone(), percentage_change))
} else {
None
}
})
.collect();

// Print the benchmarks exceeding the threshold along with the percentage change
if !benchmarks_exceeding_threshold.is_empty() {
println!("Benchmarks exceeding the 1% change threshold:");

for (benchmark_id, percentage_change) in benchmarks_exceeding_threshold {
// Color the output in red
println!("\x1b[31m {}: {:.2}%\x1b[0m", benchmark_id, percentage_change);
}

// Fail the CI with a non-zero exit code
eprintln!("Error: Benchmarks exceeding the 1% change threshold");
std::process::exit(1);
}

Ok(())
}

fn generate_and_print_table(
old_benchmarks: &[Benchmark],
new_benchmarks: &[Benchmark],
) -> Result<(), Box<dyn std::error::Error>> {
// Generate the comparison table in markdown and print it
let comparison_table_markdown = generate_comparison_table_markdown(old_benchmarks, new_benchmarks)?;
println!("{}", comparison_table_markdown);

Ok(())
}

fn generate_comparison_table_markdown(
old_benchmarks: &[Benchmark],
new_benchmarks: &[Benchmark],
) -> Result<String, Box<dyn std::error::Error>> {
let mut comparison_table = String::new();

comparison_table.push_str("| Benchmark | Base | Change | Percentage Change |\n");
comparison_table.push_str("|-----------|------|--------|-------------------|\n");

for (old, new) in old_benchmarks.iter().zip(new_benchmarks) {
let old_estimate = format_value(old.typical.estimate, &old.typical.unit);
let new_estimate = format_value(new.typical.estimate, &new.typical.unit);
let percentage_change = calculate_percentage_change(old.typical.estimate, new.typical.estimate);

// Modify the formatting to display converted numbers
comparison_table.push_str(&format!(
"| {} | {} | {} | {:.2}% |\n",
old.id, old_estimate, new_estimate, percentage_change
));
}

Ok(comparison_table)
}

fn format_value(value: f64, unit: &str) -> String {
match unit {
"ns" if value >= 1000.0 => format!("{:.2} μs", value / 1000.0),
"μs" if value >= 1000.0 => format!("{:.2} ms", value / 1000.0),
"ms" if value >= 1000.0 => format!("{:.2} s", value / 1000.0),
_ => format!("{:.2} {}", value, unit),
}
}

fn calculate_percentage_change(old_value: f64, new_value: f64) -> f64 {
if old_value == 0.0 {
0.0
} else {
((new_value - old_value) / old_value) * 100.0
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this file to /scripts

Loading
Loading