Skip to content

Commit

Permalink
Add bench for backtracking
Browse files Browse the repository at this point in the history
  • Loading branch information
x-hgg-x committed Nov 18, 2024
1 parent 51d38dd commit e8161fa
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 4 deletions.
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ include = ["Cargo.toml", "LICENSE", "README.md", "src/**", "tests/**", "examples

[dependencies]
indexmap = "2.6.0"
log = "0.4.22" # for debug logs in tests
# for debug logs in tests
log = "0.4.22"
priority-queue = "2.1.1"
rustc-hash = ">=1.0.0, <3.0.0"
serde = { version = "1.0", features = ["derive"], optional = true }
Expand All @@ -42,6 +43,10 @@ version-ranges = { version = "0.1.0", path = "version-ranges", features = ["prop
[features]
serde = ["dep:serde", "version-ranges/serde"]

[[bench]]
name = "backtracking"
harness = false

[[bench]]
name = "large_case"
harness = false
Expand Down
98 changes: 98 additions & 0 deletions benches/backtracking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-License-Identifier: MPL-2.0

//! This bench monitors the performance of backtracking and term intersection.
//!
//! Dependencies are constructed in a way that all versions need to be tested before finding a solution.
use criterion::*;
use pubgrub::OfflineDependencyProvider;
use version_ranges::Ranges;

/// This benchmark is a simplified reproduction of one of the patterns found in the `solana-*` crates from Cargo:
/// * `solana-archiver-lib v1.1.12` depends on many layers of other solana crates with req `>= 1.1.12`.
/// * each version `1.x.y` higher than `1.5.15` of a solana crate depends on other solana crates with req `= 1.x.y`.
/// * `solana-crate-features` depends on `cc` with the `num_cpus` feature, which doesn't exist in recent versions of `cc`.
fn backtracking_singletons(c: &mut Criterion, package_count: u32, version_count: u32) {
let mut dependency_provider = OfflineDependencyProvider::<u32, Ranges<u32>>::new();

dependency_provider.add_dependencies(0u32, 0u32, [(1u32, Ranges::full())]);
dependency_provider.add_dependencies(1u32, 0u32, []);

for n in 1..package_count {
for v in 1..version_count {
dependency_provider.add_dependencies(n, v, [(n + 1, Ranges::singleton(v))]);
}
}

c.bench_function("backtracking_singletons", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
})
});
}

/// This benchmark is a simplified reproduction of one of the patterns found in the `solana-*` crates from Cargo:
/// * `solana-archiver-lib v1.1.12` depends on many layers of other solana crates with req `>= 1.1.12`.
/// * `solana-archiver-lib v1.1.12` also depends on `ed25519-dalek v1.0.0-pre.3`.
/// * each version `1.x.y` higher than `1.5.15` of a solana crate depends on other solana crates with req `= 1.x.y`.
/// * `solana-crate-features >= 1.2.17` depends on `ed25519-dalek v1.0.0-pre.4` or a higher incompatible version.
fn backtracking_disjoint_versions(c: &mut Criterion, package_count: u32, version_count: u32) {
let mut dependency_provider = OfflineDependencyProvider::<u32, Ranges<u32>>::new();

let root_deps = [(1u32, Ranges::full()), (u32::MAX, Ranges::singleton(0u32))];
dependency_provider.add_dependencies(0u32, 0u32, root_deps);

dependency_provider.add_dependencies(1u32, 0u32, []);

for n in 1..package_count {
for v in 1..version_count {
dependency_provider.add_dependencies(n, v, [(n + 1, Ranges::singleton(v))]);
}
}
for v in 1..version_count {
dependency_provider.add_dependencies(package_count, v, [(u32::MAX, Ranges::singleton(v))]);
}

for v in 0..version_count {
dependency_provider.add_dependencies(u32::MAX, v, []);
}

c.bench_function("backtracking_disjoint_versions", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
})
});
}

/// This benchmark is a simplified reproduction of one of the patterns found in the `solana-*` crates from Cargo:
/// * `solana-archiver-lib v1.1.12` depends on many layers of other solana crates with req `>= 1.1.12`.
/// * each version `1.x.y` lower than `1.5.14` of a solana crate depends on other solana crates with req `>= 1.x.y`.
/// * `solana-crate-features` depends on `cc` with the `num_cpus` feature, which doesn't exist in recent versions of `cc`.
fn backtracking_ranges(c: &mut Criterion, package_count: u32, version_count: u32) {
let mut dependency_provider = OfflineDependencyProvider::<u32, Ranges<u32>>::new();

dependency_provider.add_dependencies(0u32, 0u32, [(1u32, Ranges::full())]);
dependency_provider.add_dependencies(1u32, 0u32, []);

for n in 1..package_count {
for v in 1..version_count {
let r = Ranges::higher_than(version_count - v);
dependency_provider.add_dependencies(n, v, [(n + 1, r)]);
}
}

c.bench_function("backtracking_ranges", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
})
});
}

fn bench_group(c: &mut Criterion) {
backtracking_singletons(c, 100, 500);
backtracking_disjoint_versions(c, 300, 200);
backtracking_ranges(c, 5, 200);
}

criterion_group!(benches, bench_group);
criterion_main!(benches);
1 change: 1 addition & 0 deletions benches/large_case.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: MPL-2.0

use std::time::Duration;

use criterion::*;
Expand Down
4 changes: 2 additions & 2 deletions benches/sudoku.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ fn from_board(b: &str) -> Vec<(SudokuPackage, Range<Arc<usize>>)> {
if let Some(val) = val.chars().next().unwrap().to_digit(10) {
out.push((
SudokuPackage::Cell {
row: (row + 1).try_into().unwrap(),
col: (col + 1).try_into().unwrap(),
row: row + 1,
col: col + 1,
},
Range::singleton(val as usize),
));
Expand Down
2 changes: 1 addition & 1 deletion test-examples/large_case_u16_NumberVersion.ron
Original file line number Diff line number Diff line change
Expand Up @@ -5521,4 +5521,4 @@
18: {},
19: {},
},
}
}

0 comments on commit e8161fa

Please sign in to comment.