rls: Refactor estimatedSizeBytes updates (#12145)

Just use a regular method instead of reusing the EvictionListener API.
Fix a few comments as well. Both of these changes were based on review
comments to pre-existing code in #11203.

Contributes to #11243
This commit is contained in:
Eric Anderson 2025-06-12 04:01:19 +00:00 committed by GitHub
parent 30f6a4db77
commit 13fe008044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 14 additions and 25 deletions

View File

@ -43,7 +43,8 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
private final LinkedHashMap<K, SizedValue> delegate; private final LinkedHashMap<K, SizedValue> delegate;
private final Ticker ticker; private final Ticker ticker;
private final EvictionListener<K, SizedValue> evictionListener; @Nullable
private final EvictionListener<K, V> evictionListener;
private long estimatedSizeBytes; private long estimatedSizeBytes;
private long estimatedMaxSizeBytes; private long estimatedMaxSizeBytes;
@ -53,7 +54,7 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
final Ticker ticker) { final Ticker ticker) {
checkState(estimatedMaxSizeBytes > 0, "max estimated cache size should be positive"); checkState(estimatedMaxSizeBytes > 0, "max estimated cache size should be positive");
this.estimatedMaxSizeBytes = estimatedMaxSizeBytes; this.estimatedMaxSizeBytes = estimatedMaxSizeBytes;
this.evictionListener = new SizeHandlingEvictionListener(evictionListener); this.evictionListener = evictionListener;
this.ticker = checkNotNull(ticker, "ticker"); this.ticker = checkNotNull(ticker, "ticker");
delegate = new LinkedHashMap<K, SizedValue>( delegate = new LinkedHashMap<K, SizedValue>(
// rough estimate or minimum hashmap default // rough estimate or minimum hashmap default
@ -135,7 +136,7 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
estimatedSizeBytes += size; estimatedSizeBytes += size;
existing = delegate.put(key, new SizedValue(size, value)); existing = delegate.put(key, new SizedValue(size, value));
if (existing != null) { if (existing != null) {
evictionListener.onEviction(key, existing, EvictionType.REPLACED); fireOnEviction(key, existing, EvictionType.REPLACED);
} }
return existing == null ? null : existing.value; return existing == null ? null : existing.value;
} }
@ -174,7 +175,7 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
checkNotNull(cause, "cause"); checkNotNull(cause, "cause");
SizedValue existing = delegate.remove(key); SizedValue existing = delegate.remove(key);
if (existing != null) { if (existing != null) {
evictionListener.onEviction(key, existing, cause); fireOnEviction(key, existing, cause);
} }
return existing == null ? null : existing.value; return existing == null ? null : existing.value;
} }
@ -185,7 +186,7 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
while (iterator.hasNext()) { while (iterator.hasNext()) {
Map.Entry<K, SizedValue> entry = iterator.next(); Map.Entry<K, SizedValue> entry = iterator.next();
if (entry.getValue() != null) { if (entry.getValue() != null) {
evictionListener.onEviction(entry.getKey(), entry.getValue(), EvictionType.EXPLICIT); fireOnEviction(entry.getKey(), entry.getValue(), EvictionType.EXPLICIT);
} }
iterator.remove(); iterator.remove();
} }
@ -215,14 +216,13 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
protected final boolean fitToLimit() { protected final boolean fitToLimit() {
boolean removedAnyUnexpired = false; boolean removedAnyUnexpired = false;
if (estimatedSizeBytes <= estimatedMaxSizeBytes) { if (estimatedSizeBytes <= estimatedMaxSizeBytes) {
// new size is larger no need to do cleanup
return false; return false;
} }
// cleanup expired entries // cleanup expired entries
long now = ticker.read(); long now = ticker.read();
cleanupExpiredEntries(now); cleanupExpiredEntries(now);
// cleanup eldest entry until new size limit // cleanup eldest entry until the size of all entries fits within the limit
Iterator<Map.Entry<K, SizedValue>> lruIter = delegate.entrySet().iterator(); Iterator<Map.Entry<K, SizedValue>> lruIter = delegate.entrySet().iterator();
while (lruIter.hasNext() && estimatedMaxSizeBytes < this.estimatedSizeBytes) { while (lruIter.hasNext() && estimatedMaxSizeBytes < this.estimatedSizeBytes) {
Map.Entry<K, SizedValue> entry = lruIter.next(); Map.Entry<K, SizedValue> entry = lruIter.next();
@ -230,8 +230,8 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
break; // Violates some constraint like minimum age so stop our cleanup break; // Violates some constraint like minimum age so stop our cleanup
} }
lruIter.remove(); lruIter.remove();
// eviction listener will update the estimatedSizeBytes // fireOnEviction will update the estimatedSizeBytes
evictionListener.onEviction(entry.getKey(), entry.getValue(), EvictionType.SIZE); fireOnEviction(entry.getKey(), entry.getValue(), EvictionType.SIZE);
removedAnyUnexpired = true; removedAnyUnexpired = true;
} }
return removedAnyUnexpired; return removedAnyUnexpired;
@ -270,7 +270,7 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
Map.Entry<K, SizedValue> entry = lruIter.next(); Map.Entry<K, SizedValue> entry = lruIter.next();
if (isExpired(entry.getKey(), entry.getValue().value, now)) { if (isExpired(entry.getKey(), entry.getValue().value, now)) {
lruIter.remove(); lruIter.remove();
evictionListener.onEviction(entry.getKey(), entry.getValue(), EvictionType.EXPIRED); fireOnEviction(entry.getKey(), entry.getValue(), EvictionType.EXPIRED);
removedAny = true; removedAny = true;
maxExpiredEntries--; maxExpiredEntries--;
} }
@ -283,21 +283,10 @@ abstract class LinkedHashLruCache<K, V> implements LruCache<K, V> {
invalidateAll(); invalidateAll();
} }
/** A {@link EvictionListener} keeps track of size. */ private void fireOnEviction(K key, SizedValue value, EvictionType cause) {
private final class SizeHandlingEvictionListener implements EvictionListener<K, SizedValue> {
private final EvictionListener<K, V> delegate;
SizeHandlingEvictionListener(@Nullable EvictionListener<K, V> delegate) {
this.delegate = delegate;
}
@Override
public void onEviction(K key, SizedValue value, EvictionType cause) {
estimatedSizeBytes -= value.size; estimatedSizeBytes -= value.size;
if (delegate != null) { if (evictionListener != null) {
delegate.onEviction(key, value.value, cause); evictionListener.onEviction(key, value.value, cause);
}
} }
} }