benches/core_ops.rs
Ref: Size: 8.2 KiB
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use ed25519_dalek::SigningKey;
use git2::Repository;
use rand_core::OsRng;
use tempfile::TempDir;
use git_collab::dag;
use git_collab::event::{Action, Author, Event};
use git_collab::state::{IssueState, PatchState};
fn test_author() -> Author {
Author {
name: "Bench User".to_string(),
email: "bench@example.com".to_string(),
}
}
fn test_key() -> SigningKey {
SigningKey::generate(&mut OsRng)
}
fn now() -> String {
chrono::Utc::now().to_rfc3339()
}
fn init_repo(dir: &std::path::Path) -> Repository {
let repo = Repository::init(dir).expect("init repo");
{
let mut config = repo.config().unwrap();
config.set_str("user.name", "Bench User").unwrap();
config.set_str("user.email", "bench@example.com").unwrap();
}
repo
}
/// Create N issues in a repo, each with no comments. Returns the repo and temp dir.
fn setup_issues(n: usize) -> (Repository, TempDir) {
let dir = TempDir::new().unwrap();
let repo = init_repo(dir.path());
let sk = test_key();
let author = test_author();
for i in 0..n {
let event = Event {
timestamp: now(),
author: author.clone(),
action: Action::IssueOpen {
title: format!("Issue {}", i),
body: format!("Body for issue {}", i),
relates_to: None,
},
clock: 0,
};
let oid = dag::create_root_event(&repo, &event, &sk).unwrap();
let ref_name = format!("refs/collab/issues/{}", oid);
repo.reference(&ref_name, oid, false, "bench").unwrap();
}
(repo, dir)
}
/// Create N patches in a repo. Returns the repo and temp dir.
fn setup_patches(n: usize) -> (Repository, TempDir) {
let dir = TempDir::new().unwrap();
let repo = init_repo(dir.path());
let sk = test_key();
let author = test_author();
for i in 0..n {
let event = Event {
timestamp: now(),
author: author.clone(),
action: Action::PatchCreate {
title: format!("Patch {}", i),
body: format!("Body for patch {}", i),
base_ref: "main".to_string(),
branch: format!("feature-{}", i),
fixes: None,
commit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(),
tree: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb".to_string(),
base_commit: None,
},
clock: 0,
};
let oid = dag::create_root_event(&repo, &event, &sk).unwrap();
let ref_name = format!("refs/collab/patches/{}", oid);
repo.reference(&ref_name, oid, false, "bench").unwrap();
}
(repo, dir)
}
/// Create a single issue with N comment events appended. Returns (repo, ref_name, id, tempdir).
fn setup_issue_with_comments(n: usize) -> (Repository, String, String, TempDir) {
let dir = TempDir::new().unwrap();
let repo = init_repo(dir.path());
let sk = test_key();
let author = test_author();
let open_event = Event {
timestamp: now(),
author: author.clone(),
action: Action::IssueOpen {
title: "Big issue".to_string(),
body: "An issue with many comments".to_string(),
relates_to: None,
},
clock: 0,
};
let oid = dag::create_root_event(&repo, &open_event, &sk).unwrap();
let id = oid.to_string();
let ref_name = format!("refs/collab/issues/{}", id);
repo.reference(&ref_name, oid, false, "bench").unwrap();
for i in 0..n {
let event = Event {
timestamp: now(),
author: author.clone(),
action: Action::IssueComment {
body: format!("Comment number {}", i),
},
clock: 0,
};
dag::append_event(&repo, &ref_name, &event, &sk).unwrap();
}
(repo, ref_name, id, dir)
}
fn bench_list_issues(c: &mut Criterion) {
let mut group = c.benchmark_group("list_issues");
for count in [10, 100, 1000] {
let (repo, _dir) = setup_issues(count);
group.bench_with_input(
BenchmarkId::from_parameter(count),
&count,
|b, _| {
b.iter(|| {
let issues = git_collab::state::list_issues(&repo).unwrap();
assert_eq!(issues.len(), count);
});
},
);
}
group.finish();
}
fn bench_list_patches(c: &mut Criterion) {
let mut group = c.benchmark_group("list_patches");
for count in [10, 100, 1000] {
let (repo, _dir) = setup_patches(count);
group.bench_with_input(
BenchmarkId::from_parameter(count),
&count,
|b, _| {
b.iter(|| {
let patches = git_collab::state::list_patches(&repo).unwrap();
assert_eq!(patches.len(), count);
});
},
);
}
group.finish();
}
fn bench_walk_events(c: &mut Criterion) {
let mut group = c.benchmark_group("walk_events");
for count in [10, 100, 500] {
let (repo, ref_name, _id, _dir) = setup_issue_with_comments(count);
group.bench_with_input(
BenchmarkId::from_parameter(count),
&count,
|b, _| {
b.iter(|| {
let events = dag::walk_events(&repo, &ref_name).unwrap();
// 1 open + N comments
assert_eq!(events.len(), count + 1);
});
},
);
}
group.finish();
}
fn bench_issue_from_ref(c: &mut Criterion) {
let mut group = c.benchmark_group("issue_from_ref");
for count in [10, 100, 500] {
let (repo, ref_name, id, _dir) = setup_issue_with_comments(count);
group.bench_with_input(
BenchmarkId::from_parameter(count),
&count,
|b, _| {
b.iter(|| {
let state = IssueState::from_ref(&repo, &ref_name, &id).unwrap();
assert_eq!(state.comments.len(), count);
});
},
);
}
group.finish();
}
fn bench_patch_from_ref(c: &mut Criterion) {
let mut group = c.benchmark_group("patch_from_ref");
let dir = TempDir::new().unwrap();
let repo = init_repo(dir.path());
let sk = test_key();
let author = test_author();
// Create a patch with many comments
for count in [10, 100, 500] {
let create_event = Event {
timestamp: now(),
author: author.clone(),
action: Action::PatchCreate {
title: format!("Patch with {} comments", count),
body: "A patch".to_string(),
base_ref: "main".to_string(),
branch: format!("feature-bench-{}", count),
fixes: None,
commit: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(),
tree: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb".to_string(),
base_commit: None,
},
clock: 0,
};
let oid = dag::create_root_event(&repo, &create_event, &sk).unwrap();
let id = oid.to_string();
let ref_name = format!("refs/collab/patches/{}", id);
repo.reference(&ref_name, oid, false, "bench").unwrap();
for i in 0..count {
let event = Event {
timestamp: now(),
author: author.clone(),
action: Action::PatchComment {
body: format!("Patch comment {}", i),
},
clock: 0,
};
dag::append_event(&repo, &ref_name, &event, &sk).unwrap();
}
group.bench_with_input(
BenchmarkId::from_parameter(count),
&count,
|b, _| {
b.iter(|| {
let state = PatchState::from_ref(&repo, &ref_name, &id).unwrap();
assert_eq!(state.comments.len(), count);
});
},
);
}
group.finish();
}
criterion_group!(
benches,
bench_list_issues,
bench_list_patches,
bench_walk_events,
bench_issue_from_ref,
bench_patch_from_ref,
);
criterion_main!(benches);