Skip to content

Commit

Permalink
[MRESOLVER-587] Memory usage improvements
Browse files Browse the repository at this point in the history
Do not use Artifact instance as keys, and intern the
List<Dependency> on artifact descriptors as well.

---

https://issues.apache.org/jira/browse/MRESOLVER-587
  • Loading branch information
cstamas committed Jul 13, 2024
1 parent d13019c commit 6abbe0d
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResult;
import org.eclipse.aether.util.ConfigUtils;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
import org.eclipse.aether.version.Version;
import org.eclipse.aether.version.VersionConstraint;

Expand Down Expand Up @@ -90,12 +91,17 @@ public final class DataPool {
*/
public static final String CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR = CONFIG_PROPS_PREFIX + "descriptor";

private static final String CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS =
"aether.dependencyCollector.pool.dependencyLists";

private static final String ARTIFACT_POOL = DataPool.class.getName() + "$Artifact";

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

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

private static final String DEPENDENCY_LISTS_POOL = DataPool.class.getName() + "$DependencyLists";

public static final ArtifactDescriptorResult NO_DESCRIPTOR =
new ArtifactDescriptorResult(new ArtifactDescriptorRequest());

Expand All @@ -112,7 +118,12 @@ public final class DataPool {
/**
* Descriptor interning pool, lives across session (if session carries non-null {@link RepositoryCache}).
*/
private final InternPool<Object, Descriptor> descriptors;
private final InternPool<DescriptorKey, Descriptor> descriptors;

/**
* {@link Dependency} list interning pool, lives across session (if session carries non-null {@link RepositoryCache}).
*/
private final InternPool<List<Dependency>, List<Dependency>> dependencyLists;

/**
* Constraint cache, lives during single collection invocation (same as this DataPool instance).
Expand All @@ -130,11 +141,14 @@ public DataPool(RepositorySystemSession session) {

InternPool<Artifact, Artifact> artifactsPool = null;
InternPool<Dependency, Dependency> dependenciesPool = null;
InternPool<Object, Descriptor> descriptorsPool = null;
InternPool<DescriptorKey, Descriptor> descriptorsPool = null;
InternPool<List<Dependency>, List<Dependency>> dependencyListsPool = null;
if (cache != null) {
artifactsPool = (InternPool<Artifact, Artifact>) cache.get(session, ARTIFACT_POOL);
dependenciesPool = (InternPool<Dependency, Dependency>) cache.get(session, DEPENDENCY_POOL);
descriptorsPool = (InternPool<Object, Descriptor>) cache.get(session, DESCRIPTORS);
descriptorsPool = (InternPool<DescriptorKey, Descriptor>) cache.get(session, DESCRIPTORS);
dependencyListsPool =
(InternPool<List<Dependency>, List<Dependency>>) cache.get(session, DEPENDENCY_LISTS_POOL);
}

if (artifactsPool == null) {
Expand Down Expand Up @@ -164,9 +178,20 @@ public DataPool(RepositorySystemSession session) {
}
}

if (dependencyListsPool == null) {
String dependencyListsPoolType =
ConfigUtils.getString(session, HARD, CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY_LISTS);

dependencyListsPool = createPool(dependencyListsPoolType);
if (cache != null) {
cache.put(session, DEPENDENCY_LISTS_POOL, dependencyListsPool);
}
}

this.artifacts = artifactsPool;
this.dependencies = dependenciesPool;
this.descriptors = descriptorsPool;
this.dependencyLists = dependencyListsPool;

this.constraints = new ConcurrentHashMap<>(256);
this.nodes = new ConcurrentHashMap<>(256);
Expand All @@ -180,26 +205,32 @@ public Dependency intern(Dependency dependency) {
return dependencies.intern(dependency, dependency);
}

public Object toKey(ArtifactDescriptorRequest request) {
return request.getArtifact();
public DescriptorKey toKey(ArtifactDescriptorRequest request) {
return new DescriptorKey(request.getArtifact());
}

public ArtifactDescriptorResult getDescriptor(Object key, ArtifactDescriptorRequest request) {
public ArtifactDescriptorResult getDescriptor(DescriptorKey key, ArtifactDescriptorRequest request) {
Descriptor descriptor = descriptors.get(key);
if (descriptor != null) {
return descriptor.toResult(request);
}
return null;
}

public void putDescriptor(Object key, ArtifactDescriptorResult result) {
public void putDescriptor(DescriptorKey key, ArtifactDescriptorResult result) {
result.setDependencies(intern(result.getDependencies()));
result.setManagedDependencies(intern(result.getManagedDependencies()));
descriptors.intern(key, new GoodDescriptor(result));
}

public void putDescriptor(Object key, ArtifactDescriptorException e) {
public void putDescriptor(DescriptorKey key, ArtifactDescriptorException e) {
descriptors.intern(key, BadDescriptor.INSTANCE);
}

private List<Dependency> intern(List<Dependency> dependencies) {
return dependencyLists.intern(dependencies, dependencies);
}

public Object toKey(VersionRangeRequest request) {
return new ConstraintKey(request);
}
Expand Down Expand Up @@ -234,8 +265,37 @@ public void putChildren(Object key, List<DependencyNode> children) {
nodes.put(key, children);
}

abstract static class Descriptor {
public static final class DescriptorKey {
private final String artifactKey;

private DescriptorKey(Artifact artifact) {
this.artifactKey = ArtifactIdUtils.toId(artifact);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DescriptorKey that = (DescriptorKey) o;
return Objects.equals(artifactKey, that.artifactKey);
}

@Override
public int hashCode() {
return Objects.hashCode(artifactKey);
}

@Override
public String toString() {
return getClass().getSimpleName() + "{" + "artifactKey='" + artifactKey + '\'' + '}';
}
}

abstract static class Descriptor {
public abstract ArtifactDescriptorResult toResult(ArtifactDescriptorRequest request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ protected ArtifactDescriptorResult resolveCachedArtifactDescriptor(
Dependency d,
Results results,
List<DependencyNode> nodes) {
Object key = pool.toKey(descriptorRequest);
DataPool.DescriptorKey key = pool.toKey(descriptorRequest);
ArtifactDescriptorResult descriptorResult = pool.getDescriptor(key, descriptorRequest);
if (descriptorResult == null) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void testArtifactDescriptorCaching() {
result.addAlias(new DefaultArtifact("gid:alias:4"));

DataPool pool = newDataPool();
Object key = pool.toKey(request);
DataPool.DescriptorKey key = pool.toKey(request);
pool.putDescriptor(key, result);
ArtifactDescriptorResult cached = pool.getDescriptor(key, request);
assertNotNull(cached);
Expand Down

0 comments on commit 6abbe0d

Please sign in to comment.