This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new f7a542b9 [MRESOLVER-320] Return to original pool setup (#243)
f7a542b9 is described below
commit f7a542b9ff091cf5bc3d9e71523db40d8a944f66
Author: Tamas Cservenak <[email protected]>
AuthorDate: Wed Feb 15 14:30:31 2023 +0100
[MRESOLVER-320] Return to original pool setup (#243)
The original pool setup was always (weak, weak, hard), but by mistake. The
resolver 1.8.0 got a fix for reported MRESOLVER-250: (that did lower the memory
consumption but added 10% execution time overhead). The fix for MRESOLVER-250
caused that GC collect descriptors, so during collection models were
continuously been rebuilt, but this operation is all but "cheap" (a lot of CPU
and a lot of IO).
This commit rewrites the pools, makes them configurable (for artifacts,
dependencies and descriptors/POMs) . With this PR now pools are configurable as
well (as hard+hard+hard setup may offer even speedup at cost of more heap
usage).
It also FIXES a bug creeped into master (was never released) where
interning pool misbehaves: it was able to return null value.
---
https://issues.apache.org/jira/browse/MRESOLVER-320
---
.../aether/internal/impl/collect/DataPool.java | 51 ++++++++++------------
src/site/markdown/configuration.md | 4 +-
2 files changed, 27 insertions(+), 28 deletions(-)
diff --git
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
index 70b1d55d..a531b3ff 100644
---
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
+++
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
@@ -54,7 +54,11 @@ import org.eclipse.aether.version.VersionConstraint;
*/
public final class DataPool
{
- private static final String CONFIG_PROP_COLLECTOR_POOL =
"aether.dependencyCollector.pool";
+ private static final String CONFIG_PROP_COLLECTOR_POOL_ARTIFACT =
"aether.dependencyCollector.pool.artifact";
+
+ private static final String CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY =
"aether.dependencyCollector.pool.dependency";
+
+ private static final String CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR =
"aether.dependencyCollector.pool.descriptor";
private static final String ARTIFACT_POOL = DataPool.class.getName() +
"$Artifact";
@@ -94,7 +98,6 @@ public final class DataPool
public DataPool( RepositorySystemSession session )
{
final RepositoryCache cache = session.getCache();
- final String poolType = ConfigUtils.getString( session, HARD,
CONFIG_PROP_COLLECTOR_POOL );
InternPool<Artifact, Artifact> artifactsPool = null;
InternPool<Dependency, Dependency> dependenciesPool = null;
@@ -108,7 +111,9 @@ public final class DataPool
if ( artifactsPool == null )
{
- artifactsPool = createPool( poolType );
+ String artifactPoolType = ConfigUtils.getString( session, WEAK,
CONFIG_PROP_COLLECTOR_POOL_ARTIFACT );
+
+ artifactsPool = createPool( artifactPoolType );
if ( cache != null )
{
cache.put( session, ARTIFACT_POOL, artifactsPool );
@@ -117,7 +122,9 @@ public final class DataPool
if ( dependenciesPool == null )
{
- dependenciesPool = createPool( poolType );
+ String dependencyPoolType = ConfigUtils.getString( session, WEAK,
CONFIG_PROP_COLLECTOR_POOL_DEPENDENCY );
+
+ dependenciesPool = createPool( dependencyPoolType );
if ( cache != null )
{
cache.put( session, DEPENDENCY_POOL, dependenciesPool );
@@ -126,7 +133,9 @@ public final class DataPool
if ( descriptorsPool == null )
{
- descriptorsPool = createPool( poolType );
+ String descriptorPoolType = ConfigUtils.getString( session, HARD,
CONFIG_PROP_COLLECTOR_POOL_DESCRIPTOR );
+
+ descriptorsPool = createPool( descriptorPoolType );
if ( cache != null )
{
cache.put( session, DESCRIPTORS, descriptorsPool );
@@ -453,10 +462,6 @@ public final class DataPool
{
return new WeakInternPool<>();
}
- else if ( NONE.equals( type ) )
- {
- return new NoneInternPool<>();
- }
else
{
throw new IllegalArgumentException( "Unknown object pool type: '"
+ type + "'" );
@@ -467,8 +472,6 @@ public final class DataPool
private static final String WEAK = "weak";
- private static final String NONE = "none";
-
private interface InternPool<K, V>
{
V get( K key );
@@ -507,23 +510,17 @@ public final class DataPool
@Override
public V intern( K key, V value )
{
- return map.computeIfAbsent( key, k -> new WeakReference<>( value )
).get();
- }
- }
-
- private static class NoneInternPool<K, V> implements InternPool<K, V>
- {
- @Override
- public V get( K key )
- {
- return null;
- }
-
- @Override
- public V intern( K key, V value )
- {
+ WeakReference<V> pooledRef = map.get( key );
+ if ( pooledRef != null )
+ {
+ V pooled = pooledRef.get();
+ if ( pooled != null )
+ {
+ return pooled;
+ }
+ }
+ map.put( key, new WeakReference<>( value ) );
return value;
}
}
-
}
diff --git a/src/site/markdown/configuration.md
b/src/site/markdown/configuration.md
index 74749a43..e5f87062 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -52,7 +52,9 @@ Option | Type | Description | Default Value | Supports Repo
ID Suffix
`aether.dependencyCollector.impl` | String | The name of the dependency
collector implementation to use: depth-first (original) named `df`, and
breadth-first (new in 1.8.0) named `bf`. Both collectors produce equivalent
results, but they may differ performance wise, depending on project being
applied to. Our experience shows that existing `df` is well suited for smaller
to medium size projects, while `bf` may perform better on huge projects with
many dependencies. Experiment (and come ba [...]
`aether.dependencyCollector.bf.skipper` | boolean | Flag controlling whether
to skip resolving duplicate/conflicting nodes during the breadth-first (`bf`)
dependency collection process. | `true` | no
`aether.dependencyCollector.bf.threads` or `maven.artifact.threads` | int |
Number of threads to use for collecting POMs and version ranges in BF
collector. | `5` | no
-`aether.dependencyCollector.pool` | String | Flag controlling data pool type
used by dependency collector regarding heap consumption. By default uses "hard"
references (consume more heap, but is faster). Using "weak" will make resolver
much more memory conservative, at the cost of up to 10% slower collecting
dependency speed (system and Java dependent). Supported values: `"hard"`,
`"weak"`, `"none"`. | `"hard"` | no
+`aether.dependencyCollector.pool.artifact` | String | Flag controlling
interning data pool type used by dependency collector for Artifact instances,
matters for heap consumption. By default uses "weak" references (consume less
heap). Using "hard" will make it much more memory aggressive and possibly
faster (system and Java dependent). Supported values: `"hard"`, `"weak"`. |
`"weak"` | no
+`aether.dependencyCollector.pool.dependency` | String | Flag controlling
interning data pool type used by dependency collector for Dependency instances,
matters for heap consumption. By default uses "weak" references (consume less
heap). Using "hard" will make it much more memory aggressive and possibly
faster (system and Java dependent). Supported values: `"hard"`, `"weak"`. |
`"weak"` | no
+`aether.dependencyCollector.pool.descriptor` | String | Flag controlling
interning data pool type used by dependency collector for Artifact Descriptor
(POM) instances, matters for heap consumption. By default uses "hard"
references (consume more heap, but is faster). Using "weak" will make resolver
much more memory conservative, at the cost of up to 10% slower collecting
dependency speed (system and Java dependent). Supported values: `"hard"`,
`"weak"`. | `"hard"` | no
`aether.dependencyManager.verbose` | boolean | Flag controlling the verbose
mode for dependency management. If enabled, the original attributes of a
dependency before its update due to dependency managemnent will be recorded in
the node's `DependencyNode#getData()` when building a dependency graph. |
`false` | no
`aether.enhancedLocalRepository.localPrefix` | String | The prefix to use for
locally installed artifacts. | `"installed"` | no
`aether.enhancedLocalRepository.snapshotsPrefix` | String | The prefix to use
for snapshot artifacts. | `"snapshots"` | no