Skip to content

Commit

Permalink
Use an arena for packages
Browse files Browse the repository at this point in the history
  • Loading branch information
x-hgg-x committed Nov 20, 2024
1 parent 4ac6c42 commit fa26eb3
Show file tree
Hide file tree
Showing 29 changed files with 1,284 additions and 984 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
```

This pubgrub crate provides a Rust implementation of PubGrub.
It is generic and works for any type of dependency system
as long as packages (P) and versions (V) implement
the provided `Package` and `Version` traits.


## Using the pubgrub crate

Expand Down
6 changes: 3 additions & 3 deletions benches/backtracking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn backtracking_singletons(c: &mut Criterion, package_count: u32, version_count:

c.bench_function("backtracking_singletons", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
})
});
}
Expand Down Expand Up @@ -59,7 +59,7 @@ fn backtracking_disjoint_versions(c: &mut Criterion, package_count: u32, version

c.bench_function("backtracking_disjoint_versions", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
})
});
}
Expand All @@ -83,7 +83,7 @@ fn backtracking_ranges(c: &mut Criterion, package_count: u32, version_count: u32

c.bench_function("backtracking_ranges", |b| {
b.iter(|| {
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
})
});
}
Expand Down
29 changes: 23 additions & 6 deletions benches/large_case.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
// SPDX-License-Identifier: MPL-2.0
use std::fmt::{Debug, Display};
use std::hash::Hash;

use std::time::Duration;

use criterion::*;
use serde::de::Deserialize;

use pubgrub::{resolve, OfflineDependencyProvider, Package, Range, SemanticVersion, VersionSet};
use pubgrub::{resolve, Map, OfflineDependencyProvider, Range, SemanticVersion, VersionSet};

fn bench<'a, P: Package + Deserialize<'a>, VS: VersionSet + Deserialize<'a>>(
fn bench<
'a,
P: Debug + Display + Clone + Eq + Hash + Deserialize<'a>,
VS: VersionSet + Deserialize<'a>,
>(
b: &mut Bencher,
case: &'a str,
) where
<VS as VersionSet>::V: Deserialize<'a>,
{
let dependency_provider: OfflineDependencyProvider<P, VS> = ron::de::from_str(case).unwrap();
let mut dependency_provider: OfflineDependencyProvider<P, VS> =
ron::de::from_str(case).unwrap();

let dependencies = dependency_provider
.packages()
.map(|p| {
(
p.clone(),
dependency_provider.versions(p).unwrap().cloned().collect(),
)
})
.collect::<Map<_, Vec<_>>>();

b.iter(|| {
for p in dependency_provider.packages() {
for n in dependency_provider.versions(p).unwrap() {
let _ = resolve(&dependency_provider, p.clone(), n.clone());
for (p, versions) in &dependencies {
for n in versions {
let _ = resolve(&mut dependency_provider, p.clone(), n.clone());
}
}
});
Expand Down
12 changes: 8 additions & 4 deletions benches/sudoku.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,15 @@ fn solve(board: Vec<(SudokuPackage, Ranges<Arc<usize>>)>) -> SelectedDependencie
let mut dependency_provider = DP::new();
encode_constraints(&mut dependency_provider);
dependency_provider.add_dependencies(SudokuPackage::Root, Arc::new(1usize), board);
match resolve(&dependency_provider, SudokuPackage::Root, Arc::new(1usize)) {
match resolve(
&mut dependency_provider,
SudokuPackage::Root,
Arc::new(1usize),
) {
Ok(sol) => sol,
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
Err(PubGrubError::NoSolution(mut error)) => {
error.derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&error));
std::process::exit(1);
}
Err(err) => panic!("{:?}", err),
Expand Down
8 changes: 4 additions & 4 deletions examples/branching_error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ fn main() {
dependency_provider.add_dependencies("y", (2, 0, 0), []);

// Run the algorithm.
match resolve(&dependency_provider, "root", (1, 0, 0)) {
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
Ok(sol) => println!("{:?}", sol),
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
Err(PubGrubError::NoSolution(mut error)) => {
error.derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&error));
std::process::exit(1);
}
Err(err) => panic!("{:?}", err),
Expand Down
95 changes: 62 additions & 33 deletions examples/caching_dependency_provider.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,93 @@
// SPDX-License-Identifier: MPL-2.0

use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fmt::{Debug, Display};
use std::hash::Hash;

use pubgrub::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider, Ranges};
use pubgrub::{
resolve, Dependencies, DependencyConstraints, DependencyProvider, Map,
OfflineDependencyProvider, PackageArena, PackageId, Ranges,
};

type NumVS = Ranges<u32>;
type CachedDeps<V, VS> = RefCell<Map<PackageId, BTreeMap<V, DependencyConstraints<VS>>>>;

// An example implementing caching dependency provider that will
// store queried dependencies in memory and check them before querying more from remote.
struct CachingDependencyProvider<DP: DependencyProvider> {
struct CachingDependencyProvider<DP: DependencyProvider>
where
DP::P: Debug + Display + Clone + Eq + Hash,
{
remote_dependencies: DP,
cached_dependencies: RefCell<OfflineDependencyProvider<DP::P, DP::VS>>,
cached_dependencies: CachedDeps<DP::V, DP::VS>,
}

impl<DP: DependencyProvider> CachingDependencyProvider<DP> {
impl<DP: DependencyProvider> CachingDependencyProvider<DP>
where
DP::P: Debug + Display + Clone + Eq + Hash,
{
pub fn new(remote_dependencies_provider: DP) -> Self {
CachingDependencyProvider {
remote_dependencies: remote_dependencies_provider,
cached_dependencies: RefCell::new(OfflineDependencyProvider::new()),
cached_dependencies: Default::default(),
}
}
}

impl<DP: DependencyProvider<M = String>> DependencyProvider for CachingDependencyProvider<DP> {
// Caches dependencies if they were already queried
impl<DP: DependencyProvider<M = &'static str>> DependencyProvider for CachingDependencyProvider<DP>
where
DP::P: Debug + Display + Clone + Eq + Hash,
{
// Cache dependencies if they were already queried
fn get_dependencies(
&self,
package: &DP::P,
&mut self,
package_id: PackageId,
version: &DP::V,
) -> Result<Dependencies<DP::P, DP::VS, DP::M>, DP::Err> {
package_store: &mut PackageArena<Self::P>,
) -> Result<Dependencies<DP::VS, DP::M>, DP::Err> {
let mut cache = self.cached_dependencies.borrow_mut();
match cache.get_dependencies(package, version) {
Ok(Dependencies::Unavailable(_)) => {
let dependencies = self.remote_dependencies.get_dependencies(package, version);
match dependencies {
Ok(Dependencies::Available(dependencies)) => {
cache.add_dependencies(
package.clone(),
version.clone(),
dependencies.clone(),
);
Ok(Dependencies::Available(dependencies))
}
Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)),
error @ Err(_) => error,
}
if let Some(deps) = cache.get(&package_id).and_then(|vmap| vmap.get(version)) {
return Ok(Dependencies::Available(deps.clone()));
}

match self
.remote_dependencies
.get_dependencies(package_id, version, package_store)
{
Ok(Dependencies::Available(deps)) => {
cache
.entry(package_id)
.or_default()
.insert(version.clone(), deps.clone());
Ok(Dependencies::Available(deps))
}
Ok(dependencies) => Ok(dependencies),
Err(_) => unreachable!(),

Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)),
error @ Err(_) => error,
}
}

fn choose_version(&self, package: &DP::P, ranges: &DP::VS) -> Result<Option<DP::V>, DP::Err> {
self.remote_dependencies.choose_version(package, ranges)
fn choose_version(
&mut self,
package_id: PackageId,
ranges: &DP::VS,
package_store: &PackageArena<Self::P>,
) -> Result<Option<DP::V>, DP::Err> {
self.remote_dependencies
.choose_version(package_id, ranges, package_store)
}

type Priority = DP::Priority;

fn prioritize(&self, package: &DP::P, ranges: &DP::VS) -> Self::Priority {
self.remote_dependencies.prioritize(package, ranges)
fn prioritize(
&mut self,
package_id: PackageId,
ranges: &DP::VS,
package_store: &PackageArena<Self::P>,
) -> Self::Priority {
self.remote_dependencies
.prioritize(package_id, ranges, package_store)
}

type Err = DP::Err;
Expand All @@ -76,9 +105,9 @@ fn main() {
// Add dependencies as needed. Here only root package is added.
remote_dependencies_provider.add_dependencies("root", 1u32, Vec::new());

let caching_dependencies_provider =
let mut caching_dependencies_provider =
CachingDependencyProvider::new(remote_dependencies_provider);

let solution = resolve(&caching_dependencies_provider, "root", 1u32);
let solution = resolve(&mut caching_dependencies_provider, "root", 1u32);
println!("Solution: {:?}", solution);
}
2 changes: 1 addition & 1 deletion examples/doc_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ fn main() {
dependency_provider.add_dependencies("icons", 1u32, []);

// Run the algorithm.
let solution = resolve(&dependency_provider, "root", 1u32);
let solution = resolve(&mut dependency_provider, "root", 1u32);
println!("Solution: {:?}", solution);
}
8 changes: 4 additions & 4 deletions examples/doc_interface_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ fn main() {
dependency_provider.add_dependencies("intl", (5, 0, 0), []);

// Run the algorithm.
match resolve(&dependency_provider, "root", (1, 0, 0)) {
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
Ok(sol) => println!("{:?}", sol),
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
Err(PubGrubError::NoSolution(mut error)) => {
error.derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&error));
}
Err(err) => panic!("{:?}", err),
};
Expand Down
8 changes: 4 additions & 4 deletions examples/doc_interface_semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ fn main() {
dependency_provider.add_dependencies("icons", (2, 0, 0), []);

// Run the algorithm.
match resolve(&dependency_provider, "root", (1, 0, 0)) {
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
Ok(sol) => println!("{:?}", sol),
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
Err(PubGrubError::NoSolution(mut error)) => {
error.derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&error));
}
Err(err) => panic!("{:?}", err),
};
Expand Down
8 changes: 4 additions & 4 deletions examples/linear_error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ fn main() {
dependency_provider.add_dependencies("baz", (3, 0, 0), []);

// Run the algorithm.
match resolve(&dependency_provider, "root", (1, 0, 0)) {
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
Ok(sol) => println!("{:?}", sol),
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
Err(PubGrubError::NoSolution(mut error)) => {
error.derivation_tree.collapse_no_versions();
eprintln!("{}", DefaultStringReporter::report(&error));
std::process::exit(1);
}
Err(err) => panic!("{:?}", err),
Expand Down
Loading

0 comments on commit fa26eb3

Please sign in to comment.