Skip to content

Commit fa26eb3

Browse files
committed
Use an arena for packages
1 parent 4ac6c42 commit fa26eb3

29 files changed

+1284
-984
lines changed

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,6 @@ So, because root depends on both menu >=1.0.0 and intl >=5.0.0,
2929
```
3030

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

3733
## Using the pubgrub crate
3834

benches/backtracking.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn backtracking_singletons(c: &mut Criterion, package_count: u32, version_count:
2626

2727
c.bench_function("backtracking_singletons", |b| {
2828
b.iter(|| {
29-
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
29+
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
3030
})
3131
});
3232
}
@@ -59,7 +59,7 @@ fn backtracking_disjoint_versions(c: &mut Criterion, package_count: u32, version
5959

6060
c.bench_function("backtracking_disjoint_versions", |b| {
6161
b.iter(|| {
62-
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
62+
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
6363
})
6464
});
6565
}
@@ -83,7 +83,7 @@ fn backtracking_ranges(c: &mut Criterion, package_count: u32, version_count: u32
8383

8484
c.bench_function("backtracking_ranges", |b| {
8585
b.iter(|| {
86-
let _ = pubgrub::resolve(&dependency_provider, 0u32, 0u32);
86+
let _ = pubgrub::resolve(&mut dependency_provider, 0u32, 0u32);
8787
})
8888
});
8989
}

benches/large_case.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,41 @@
11
// SPDX-License-Identifier: MPL-2.0
2+
use std::fmt::{Debug, Display};
3+
use std::hash::Hash;
24

35
use std::time::Duration;
46

57
use criterion::*;
68
use serde::de::Deserialize;
79

8-
use pubgrub::{resolve, OfflineDependencyProvider, Package, Range, SemanticVersion, VersionSet};
10+
use pubgrub::{resolve, Map, OfflineDependencyProvider, Range, SemanticVersion, VersionSet};
911

10-
fn bench<'a, P: Package + Deserialize<'a>, VS: VersionSet + Deserialize<'a>>(
12+
fn bench<
13+
'a,
14+
P: Debug + Display + Clone + Eq + Hash + Deserialize<'a>,
15+
VS: VersionSet + Deserialize<'a>,
16+
>(
1117
b: &mut Bencher,
1218
case: &'a str,
1319
) where
1420
<VS as VersionSet>::V: Deserialize<'a>,
1521
{
16-
let dependency_provider: OfflineDependencyProvider<P, VS> = ron::de::from_str(case).unwrap();
22+
let mut dependency_provider: OfflineDependencyProvider<P, VS> =
23+
ron::de::from_str(case).unwrap();
24+
25+
let dependencies = dependency_provider
26+
.packages()
27+
.map(|p| {
28+
(
29+
p.clone(),
30+
dependency_provider.versions(p).unwrap().cloned().collect(),
31+
)
32+
})
33+
.collect::<Map<_, Vec<_>>>();
1734

1835
b.iter(|| {
19-
for p in dependency_provider.packages() {
20-
for n in dependency_provider.versions(p).unwrap() {
21-
let _ = resolve(&dependency_provider, p.clone(), n.clone());
36+
for (p, versions) in &dependencies {
37+
for n in versions {
38+
let _ = resolve(&mut dependency_provider, p.clone(), n.clone());
2239
}
2340
}
2441
});

benches/sudoku.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,15 @@ fn solve(board: Vec<(SudokuPackage, Ranges<Arc<usize>>)>) -> SelectedDependencie
123123
let mut dependency_provider = DP::new();
124124
encode_constraints(&mut dependency_provider);
125125
dependency_provider.add_dependencies(SudokuPackage::Root, Arc::new(1usize), board);
126-
match resolve(&dependency_provider, SudokuPackage::Root, Arc::new(1usize)) {
126+
match resolve(
127+
&mut dependency_provider,
128+
SudokuPackage::Root,
129+
Arc::new(1usize),
130+
) {
127131
Ok(sol) => sol,
128-
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
129-
derivation_tree.collapse_no_versions();
130-
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
132+
Err(PubGrubError::NoSolution(mut error)) => {
133+
error.derivation_tree.collapse_no_versions();
134+
eprintln!("{}", DefaultStringReporter::report(&error));
131135
std::process::exit(1);
132136
}
133137
Err(err) => panic!("{:?}", err),

examples/branching_error_reporting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ fn main() {
5454
dependency_provider.add_dependencies("y", (2, 0, 0), []);
5555

5656
// Run the algorithm.
57-
match resolve(&dependency_provider, "root", (1, 0, 0)) {
57+
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
5858
Ok(sol) => println!("{:?}", sol),
59-
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
60-
derivation_tree.collapse_no_versions();
61-
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
59+
Err(PubGrubError::NoSolution(mut error)) => {
60+
error.derivation_tree.collapse_no_versions();
61+
eprintln!("{}", DefaultStringReporter::report(&error));
6262
std::process::exit(1);
6363
}
6464
Err(err) => panic!("{:?}", err),
Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,93 @@
11
// SPDX-License-Identifier: MPL-2.0
22

33
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::fmt::{Debug, Display};
6+
use std::hash::Hash;
47

5-
use pubgrub::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider, Ranges};
8+
use pubgrub::{
9+
resolve, Dependencies, DependencyConstraints, DependencyProvider, Map,
10+
OfflineDependencyProvider, PackageArena, PackageId, Ranges,
11+
};
612

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

916
// An example implementing caching dependency provider that will
1017
// store queried dependencies in memory and check them before querying more from remote.
11-
struct CachingDependencyProvider<DP: DependencyProvider> {
18+
struct CachingDependencyProvider<DP: DependencyProvider>
19+
where
20+
DP::P: Debug + Display + Clone + Eq + Hash,
21+
{
1222
remote_dependencies: DP,
13-
cached_dependencies: RefCell<OfflineDependencyProvider<DP::P, DP::VS>>,
23+
cached_dependencies: CachedDeps<DP::V, DP::VS>,
1424
}
1525

16-
impl<DP: DependencyProvider> CachingDependencyProvider<DP> {
26+
impl<DP: DependencyProvider> CachingDependencyProvider<DP>
27+
where
28+
DP::P: Debug + Display + Clone + Eq + Hash,
29+
{
1730
pub fn new(remote_dependencies_provider: DP) -> Self {
1831
CachingDependencyProvider {
1932
remote_dependencies: remote_dependencies_provider,
20-
cached_dependencies: RefCell::new(OfflineDependencyProvider::new()),
33+
cached_dependencies: Default::default(),
2134
}
2235
}
2336
}
2437

25-
impl<DP: DependencyProvider<M = String>> DependencyProvider for CachingDependencyProvider<DP> {
26-
// Caches dependencies if they were already queried
38+
impl<DP: DependencyProvider<M = &'static str>> DependencyProvider for CachingDependencyProvider<DP>
39+
where
40+
DP::P: Debug + Display + Clone + Eq + Hash,
41+
{
42+
// Cache dependencies if they were already queried
2743
fn get_dependencies(
28-
&self,
29-
package: &DP::P,
44+
&mut self,
45+
package_id: PackageId,
3046
version: &DP::V,
31-
) -> Result<Dependencies<DP::P, DP::VS, DP::M>, DP::Err> {
47+
package_store: &mut PackageArena<Self::P>,
48+
) -> Result<Dependencies<DP::VS, DP::M>, DP::Err> {
3249
let mut cache = self.cached_dependencies.borrow_mut();
33-
match cache.get_dependencies(package, version) {
34-
Ok(Dependencies::Unavailable(_)) => {
35-
let dependencies = self.remote_dependencies.get_dependencies(package, version);
36-
match dependencies {
37-
Ok(Dependencies::Available(dependencies)) => {
38-
cache.add_dependencies(
39-
package.clone(),
40-
version.clone(),
41-
dependencies.clone(),
42-
);
43-
Ok(Dependencies::Available(dependencies))
44-
}
45-
Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)),
46-
error @ Err(_) => error,
47-
}
50+
if let Some(deps) = cache.get(&package_id).and_then(|vmap| vmap.get(version)) {
51+
return Ok(Dependencies::Available(deps.clone()));
52+
}
53+
54+
match self
55+
.remote_dependencies
56+
.get_dependencies(package_id, version, package_store)
57+
{
58+
Ok(Dependencies::Available(deps)) => {
59+
cache
60+
.entry(package_id)
61+
.or_default()
62+
.insert(version.clone(), deps.clone());
63+
Ok(Dependencies::Available(deps))
4864
}
49-
Ok(dependencies) => Ok(dependencies),
50-
Err(_) => unreachable!(),
65+
66+
Ok(Dependencies::Unavailable(reason)) => Ok(Dependencies::Unavailable(reason)),
67+
error @ Err(_) => error,
5168
}
5269
}
5370

54-
fn choose_version(&self, package: &DP::P, ranges: &DP::VS) -> Result<Option<DP::V>, DP::Err> {
55-
self.remote_dependencies.choose_version(package, ranges)
71+
fn choose_version(
72+
&mut self,
73+
package_id: PackageId,
74+
ranges: &DP::VS,
75+
package_store: &PackageArena<Self::P>,
76+
) -> Result<Option<DP::V>, DP::Err> {
77+
self.remote_dependencies
78+
.choose_version(package_id, ranges, package_store)
5679
}
5780

5881
type Priority = DP::Priority;
5982

60-
fn prioritize(&self, package: &DP::P, ranges: &DP::VS) -> Self::Priority {
61-
self.remote_dependencies.prioritize(package, ranges)
83+
fn prioritize(
84+
&mut self,
85+
package_id: PackageId,
86+
ranges: &DP::VS,
87+
package_store: &PackageArena<Self::P>,
88+
) -> Self::Priority {
89+
self.remote_dependencies
90+
.prioritize(package_id, ranges, package_store)
6291
}
6392

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

79-
let caching_dependencies_provider =
108+
let mut caching_dependencies_provider =
80109
CachingDependencyProvider::new(remote_dependencies_provider);
81110

82-
let solution = resolve(&caching_dependencies_provider, "root", 1u32);
111+
let solution = resolve(&mut caching_dependencies_provider, "root", 1u32);
83112
println!("Solution: {:?}", solution);
84113
}

examples/doc_interface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ fn main() {
1919
dependency_provider.add_dependencies("icons", 1u32, []);
2020

2121
// Run the algorithm.
22-
let solution = resolve(&dependency_provider, "root", 1u32);
22+
let solution = resolve(&mut dependency_provider, "root", 1u32);
2323
println!("Solution: {:?}", solution);
2424
}

examples/doc_interface_error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ fn main() {
7171
dependency_provider.add_dependencies("intl", (5, 0, 0), []);
7272

7373
// Run the algorithm.
74-
match resolve(&dependency_provider, "root", (1, 0, 0)) {
74+
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
7575
Ok(sol) => println!("{:?}", sol),
76-
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
77-
derivation_tree.collapse_no_versions();
78-
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
76+
Err(PubGrubError::NoSolution(mut error)) => {
77+
error.derivation_tree.collapse_no_versions();
78+
eprintln!("{}", DefaultStringReporter::report(&error));
7979
}
8080
Err(err) => panic!("{:?}", err),
8181
};

examples/doc_interface_semantic.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ fn main() {
6262
dependency_provider.add_dependencies("icons", (2, 0, 0), []);
6363

6464
// Run the algorithm.
65-
match resolve(&dependency_provider, "root", (1, 0, 0)) {
65+
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
6666
Ok(sol) => println!("{:?}", sol),
67-
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
68-
derivation_tree.collapse_no_versions();
69-
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
67+
Err(PubGrubError::NoSolution(mut error)) => {
68+
error.derivation_tree.collapse_no_versions();
69+
eprintln!("{}", DefaultStringReporter::report(&error));
7070
}
7171
Err(err) => panic!("{:?}", err),
7272
};

examples/linear_error_reporting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ fn main() {
3636
dependency_provider.add_dependencies("baz", (3, 0, 0), []);
3737

3838
// Run the algorithm.
39-
match resolve(&dependency_provider, "root", (1, 0, 0)) {
39+
match resolve(&mut dependency_provider, "root", (1, 0, 0)) {
4040
Ok(sol) => println!("{:?}", sol),
41-
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
42-
derivation_tree.collapse_no_versions();
43-
eprintln!("{}", DefaultStringReporter::report(&derivation_tree));
41+
Err(PubGrubError::NoSolution(mut error)) => {
42+
error.derivation_tree.collapse_no_versions();
43+
eprintln!("{}", DefaultStringReporter::report(&error));
4444
std::process::exit(1);
4545
}
4646
Err(err) => panic!("{:?}", err),

0 commit comments

Comments
 (0)