Skip to content

Commit cdc68ea

Browse files
authored
[MRESOLVER-587] Memory usage improvements (#536)
Do not use `Object` as descriptor key, use dedicated type. And intern the `List<Dependency>` on artifact descriptors. Also introduce "intern"-ing of ArtifactDescriptor dependencies and managedDependencies that is configurable (speed vs memory). --- https://issues.apache.org/jira/browse/MRESOLVER-587
1 parent f1be3b9 commit cdc68ea

File tree

4 files changed

+92
-12
lines changed

4 files changed

+92
-12
lines changed

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,23 @@ public final class DataPool {
5858

5959
private static final String CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR = "aether.dependencyCollector.pool.descriptor";
6060

61+
private static final String CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS =
62+
"aether.dependencyCollector.pool.dependencyLists";
63+
64+
private static final String CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_DEPENDENCIES =
65+
"aether.dependencyCollector.pool.internArtifactDescriptorDependencies";
66+
67+
private static final String CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_MANAGED_DEPENDENCIES =
68+
"aether.dependencyCollector.pool.internArtifactDescriptorManagedDependencies";
69+
6170
private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";
6271

6372
private static final String DEPENDENCY_POOL = DataPool.class.getName() + "$Dependency";
6473

6574
private static final String DESCRIPTORS = DataPool.class.getName() + "$Descriptors";
6675

76+
private static final String DEPENDENCY_LISTS_POOL = DataPool.class.getName() + "$DependencyLists";
77+
6778
public static final ArtifactDescriptorResult NO_DESCRIPTOR =
6879
new ArtifactDescriptorResult(new ArtifactDescriptorRequest());
6980

@@ -80,7 +91,12 @@ public final class DataPool {
8091
/**
8192
* Descriptor interning pool, lives across session (if session carries non-null {@link RepositoryCache}).
8293
*/
83-
private final InternPool<Object, Descriptor> descriptors;
94+
private final InternPool<DescriptorKey, Descriptor> descriptors;
95+
96+
/**
97+
* {@link Dependency} list interning pool, lives across session (if session carries non-null {@link RepositoryCache}).
98+
*/
99+
private final InternPool<List<Dependency>, List<Dependency>> dependencyLists;
84100

85101
/**
86102
* Constraint cache, lives during single collection invocation (same as this DataPool instance).
@@ -92,17 +108,29 @@ public final class DataPool {
92108
*/
93109
private final ConcurrentHashMap<Object, List<DependencyNode>> nodes;
94110

111+
private final boolean internArtifactDescriptorDependencies;
112+
113+
private final boolean internArtifactDescriptorManagedDependencies;
114+
95115
@SuppressWarnings("unchecked")
96116
public DataPool(RepositorySystemSession session) {
97117
final RepositoryCache cache = session.getCache();
98118

119+
internArtifactDescriptorDependencies = ConfigUtils.getBoolean(
120+
session, false, CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_DEPENDENCIES);
121+
internArtifactDescriptorManagedDependencies = ConfigUtils.getBoolean(
122+
session, true, CONFIG_PROP_COLLECTOR_POOL_INTERN_ARTIFACT_DESCRIPTOR_MANAGED_DEPENDENCIES);
123+
99124
InternPool<Artifact, Artifact> artifactsPool = null;
100125
InternPool<Dependency, Dependency> dependenciesPool = null;
101-
InternPool<Object, Descriptor> descriptorsPool = null;
126+
InternPool<DescriptorKey, Descriptor> descriptorsPool = null;
127+
InternPool<List<Dependency>, List<Dependency>> dependencyListsPool = null;
102128
if (cache != null) {
103129
artifactsPool = (InternPool<Artifact, Artifact>) cache.get(session, ARTIFACT_POOL);
104130
dependenciesPool = (InternPool<Dependency, Dependency>) cache.get(session, DEPENDENCY_POOL);
105-
descriptorsPool = (InternPool<Object, Descriptor>) cache.get(session, DESCRIPTORS);
131+
descriptorsPool = (InternPool<DescriptorKey, Descriptor>) cache.get(session, DESCRIPTORS);
132+
dependencyListsPool =
133+
(InternPool<List<Dependency>, List<Dependency>>) cache.get(session, DEPENDENCY_LISTS_POOL);
106134
}
107135

108136
if (artifactsPool == null) {
@@ -132,9 +160,20 @@ public DataPool(RepositorySystemSession session) {
132160
}
133161
}
134162

163+
if (dependencyListsPool == null) {
164+
String dependencyListsPoolType =
165+
ConfigUtils.getString(session, HARD, CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS);
166+
167+
dependencyListsPool = createPool(dependencyListsPoolType);
168+
if (cache != null) {
169+
cache.put(session, DEPENDENCY_LISTS_POOL, dependencyListsPool);
170+
}
171+
}
172+
135173
this.artifacts = artifactsPool;
136174
this.dependencies = dependenciesPool;
137175
this.descriptors = descriptorsPool;
176+
this.dependencyLists = dependencyListsPool;
138177

139178
this.constraints = new ConcurrentHashMap<>(256);
140179
this.nodes = new ConcurrentHashMap<>(256);
@@ -148,26 +187,36 @@ public Dependency intern(Dependency dependency) {
148187
return dependencies.intern(dependency, dependency);
149188
}
150189

151-
public Object toKey(ArtifactDescriptorRequest request) {
152-
return request.getArtifact();
190+
public DescriptorKey toKey(ArtifactDescriptorRequest request) {
191+
return new DescriptorKey(request.getArtifact());
153192
}
154193

155-
public ArtifactDescriptorResult getDescriptor(Object key, ArtifactDescriptorRequest request) {
194+
public ArtifactDescriptorResult getDescriptor(DescriptorKey key, ArtifactDescriptorRequest request) {
156195
Descriptor descriptor = descriptors.get(key);
157196
if (descriptor != null) {
158197
return descriptor.toResult(request);
159198
}
160199
return null;
161200
}
162201

163-
public void putDescriptor(Object key, ArtifactDescriptorResult result) {
202+
public void putDescriptor(DescriptorKey key, ArtifactDescriptorResult result) {
203+
if (internArtifactDescriptorDependencies) {
204+
result.setDependencies(intern(result.getDependencies()));
205+
}
206+
if (internArtifactDescriptorManagedDependencies) {
207+
result.setManagedDependencies(intern(result.getManagedDependencies()));
208+
}
164209
descriptors.intern(key, new GoodDescriptor(result));
165210
}
166211

167-
public void putDescriptor(Object key, ArtifactDescriptorException e) {
212+
public void putDescriptor(DescriptorKey key, ArtifactDescriptorException e) {
168213
descriptors.intern(key, BadDescriptor.INSTANCE);
169214
}
170215

216+
private List<Dependency> intern(List<Dependency> dependencies) {
217+
return dependencyLists.intern(dependencies, dependencies);
218+
}
219+
171220
public Object toKey(VersionRangeRequest request) {
172221
return new ConstraintKey(request);
173222
}
@@ -202,8 +251,39 @@ public void putChildren(Object key, List<DependencyNode> children) {
202251
nodes.put(key, children);
203252
}
204253

205-
abstract static class Descriptor {
254+
public static final class DescriptorKey {
255+
private final Artifact artifact;
256+
private final int hashCode;
257+
258+
private DescriptorKey(Artifact artifact) {
259+
this.artifact = artifact;
260+
this.hashCode = Objects.hashCode(artifact);
261+
}
262+
263+
@Override
264+
public boolean equals(Object o) {
265+
if (this == o) {
266+
return true;
267+
}
268+
if (o == null || getClass() != o.getClass()) {
269+
return false;
270+
}
271+
DescriptorKey that = (DescriptorKey) o;
272+
return Objects.equals(artifact, that.artifact);
273+
}
206274

275+
@Override
276+
public int hashCode() {
277+
return hashCode;
278+
}
279+
280+
@Override
281+
public String toString() {
282+
return getClass().getSimpleName() + "{" + "artifact='" + artifact + '\'' + '}';
283+
}
284+
}
285+
286+
abstract static class Descriptor {
207287
public abstract ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request);
208288
}
209289

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/BfDependencyCollector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ private ArtifactDescriptorResult resolveCachedArtifactDescriptor(
448448
RepositorySystemSession session,
449449
DependencyProcessingContext context,
450450
Results results) {
451-
Object key = pool.toKey(descriptorRequest);
451+
DataPool.DescriptorKey key = pool.toKey(descriptorRequest);
452452
ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest);
453453
if (descriptorResult == null) {
454454
try {

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/df/DfDependencyCollector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ private ArtifactDescriptorResult resolveCachedArtifactDescriptor(
375375
Dependency d,
376376
Results results,
377377
Args args) {
378-
Object key = pool.toKey(descriptorRequest);
378+
DataPool.DescriptorKey key = pool.toKey(descriptorRequest);
379379
ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest);
380380
if (descriptorResult == null) {
381381
try {

maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void testArtifactDescriptorCaching() {
5151
result.addAlias(new DefaultArtifact("gid:alias:4"));
5252

5353
DataPool pool = newDataPool();
54-
Object key = pool.toKey(request);
54+
DataPool.DescriptorKey key = pool.toKey(request);
5555
pool.putDescriptor(key, result);
5656
ArtifactDescriptorResult cached = pool.getDescriptor(key, request);
5757
assertNotNull(cached);

0 commit comments

Comments
 (0)