Make ConcurrentReferenceHashMap more JIT friendly

Update `ConcurrentReferenceHashMap` to make some methods more inline
friendly, and to manually inline a few others. These minor optimizations
don't make a great deal of difference for most applications, but seem
worthwhile since we use `ConcurrentReferenceHashMap` for many internal
caches.

Closes gh-22566
This commit is contained in:
Phillip Webb 2019-03-08 17:19:01 -08:00 committed by Juergen Hoeller
parent aa4e56b251
commit e3a86be122
1 changed files with 63 additions and 59 deletions

View File

@ -35,6 +35,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import org.springframework.lang.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap.Reference;
import org.springframework.util.ConcurrentReferenceHashMap.Restructure;
/**
* A {@link ConcurrentHashMap} that uses {@link ReferenceType#SOFT soft} or
@ -232,27 +234,24 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
@Override
@Nullable
public V get(@Nullable Object key) {
Entry<K, V> entry = getEntryIfAvailable(key);
Reference<K, V> ref = getReference(key, Restructure.WHEN_NECESSARY);
Entry<K, V> entry = (ref != null ? ref.get() : null);
return (entry != null ? entry.getValue() : null);
}
@Override
@Nullable
public V getOrDefault(@Nullable Object key, @Nullable V defaultValue) {
Entry<K, V> entry = getEntryIfAvailable(key);
Reference<K, V> ref = getReference(key, Restructure.WHEN_NECESSARY);
Entry<K, V> entry = (ref != null ? ref.get() : null);
return (entry != null ? entry.getValue() : defaultValue);
}
@Override
public boolean containsKey(@Nullable Object key) {
Entry<K, V> entry = getEntryIfAvailable(key);
return (entry != null && ObjectUtils.nullSafeEquals(entry.getKey(), key));
}
@Nullable
private Entry<K, V> getEntryIfAvailable(@Nullable Object key) {
Reference<K, V> ref = getReference(key, Restructure.WHEN_NECESSARY);
return (ref != null ? ref.get() : null);
Entry<K, V> entry = (ref != null ? ref.get() : null);
return (entry != null && ObjectUtils.nullSafeEquals(entry.getKey(), key));
}
/**
@ -573,9 +572,15 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
*/
protected final void restructureIfNecessary(boolean allowResize) {
int currCount = this.count.get();
boolean needsResize = (currCount > 0 && currCount >= this.resizeThreshold);
boolean needsResize = allowResize && (currCount > 0 && currCount >= this.resizeThreshold);
Reference<K, V> ref = this.referenceManager.pollForPurge();
if (ref != null || (needsResize && allowResize)) {
if (ref != null || (needsResize)) {
restructure(allowResize, ref);
}
}
private void restructure(boolean allowResize, Reference<K, V> ref) {
boolean needsResize;
lock();
try {
int countAfterRestructure = this.count.get();
@ -633,7 +638,6 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
unlock();
}
}
}
@Nullable
private Reference<K, V> findInChain(Reference<K, V> ref, @Nullable Object key, int hash) {