-
Notifications
You must be signed in to change notification settings - Fork 293
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2044 from DataDog/landerson/weak-cache
Replace Guava caches
- Loading branch information
Showing
17 changed files
with
305 additions
and
212 deletions.
There are no files selected for viewing
12 changes: 4 additions & 8 deletions
12
dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/WeakCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,15 @@ | ||
package datadog.trace.bootstrap; | ||
|
||
import java.util.concurrent.Callable; | ||
import datadog.trace.api.Function; | ||
|
||
public interface WeakCache<K, V> { | ||
interface Provider<K, V> { | ||
WeakCache<K, V> newWeakCache(); | ||
|
||
WeakCache<K, V> newWeakCache(final long maxSize); | ||
interface Provider { | ||
<K, V> WeakCache<K, V> newWeakCache(long maxSize); | ||
} | ||
|
||
V getIfPresent(final K key); | ||
|
||
V getIfPresentOrCompute(final K key, final Callable<? extends V> loader); | ||
|
||
V get(final K key, final Callable<? extends V> loader); | ||
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction); | ||
|
||
void put(final K key, final V value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/CLHMWeakCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package datadog.trace.agent.tooling; | ||
|
||
import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap; | ||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; | ||
import datadog.trace.api.Function; | ||
import datadog.trace.bootstrap.WeakCache; | ||
import java.util.concurrent.ConcurrentMap; | ||
|
||
public class CLHMWeakCache<K, V> implements WeakCache<K, V> { | ||
public static final class Provider implements WeakCache.Provider { | ||
@Override | ||
public <K, V> WeakCache<K, V> newWeakCache(long maxSize) { | ||
return new CLHMWeakCache<>(maxSize); | ||
} | ||
} | ||
|
||
private static final int CACHE_CONCURRENCY = | ||
Math.max(8, Runtime.getRuntime().availableProcessors()); | ||
private final WeakConcurrentMap<K, V> weakMap; | ||
private final long maxSize; | ||
|
||
public CLHMWeakCache(long maxSize) { | ||
// No parameterization because WeakKey isn't visible | ||
ConcurrentMap linkedMap = | ||
new ConcurrentLinkedHashMap.Builder() | ||
.maximumWeightedCapacity(maxSize) | ||
.concurrencyLevel(CACHE_CONCURRENCY) | ||
.build(); | ||
|
||
weakMap = new WeakConcurrentMap<>(false, true, linkedMap); | ||
|
||
this.maxSize = maxSize; | ||
} | ||
|
||
@Override | ||
public V getIfPresent(K key) { | ||
return weakMap.getIfPresent(key); | ||
} | ||
|
||
@Override | ||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { | ||
V value = weakMap.getIfPresent(key); | ||
if (value == null) { | ||
value = mappingFunction.apply(key); | ||
|
||
expungeIfNecessary(); | ||
V oldValue = weakMap.putIfProbablyAbsent(key, value); | ||
if (oldValue != null) { | ||
value = oldValue; | ||
} | ||
} | ||
|
||
return value; | ||
} | ||
|
||
@Override | ||
public void put(K key, V value) { | ||
expungeIfNecessary(); | ||
|
||
weakMap.put(key, value); | ||
} | ||
|
||
private void expungeIfNecessary() { | ||
if (weakMap.approximateSize() >= maxSize) { | ||
weakMap.expungeStaleEntries(); | ||
} | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/CaffeineWeakCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package datadog.trace.agent.tooling; | ||
|
||
import com.github.benmanes.caffeine.cache.Cache; | ||
import com.github.benmanes.caffeine.cache.Caffeine; | ||
import datadog.trace.api.Function; | ||
import datadog.trace.bootstrap.WeakCache; | ||
import datadog.trace.util.AgentTaskScheduler; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class CaffeineWeakCache<K, V> implements WeakCache<K, V> { | ||
public static final class Provider implements WeakCache.Provider { | ||
@Override | ||
public <K, V> WeakCache<K, V> newWeakCache(long maxSize) { | ||
return new CaffeineWeakCache<>(maxSize); | ||
} | ||
} | ||
|
||
private final Cache<K, V> cache; | ||
|
||
public CaffeineWeakCache(long maxSize) { | ||
cache = | ||
Caffeine.newBuilder() | ||
.weakKeys() | ||
.maximumSize(maxSize) | ||
.expireAfterAccess(10, TimeUnit.MINUTES) | ||
.executor(AgentTaskScheduler.INSTANCE) | ||
.build(); | ||
} | ||
|
||
@Override | ||
public V getIfPresent(K key) { | ||
return cache.getIfPresent(key); | ||
} | ||
|
||
@Override | ||
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { | ||
// Unable to use cache.get() directly because it relies on java.util.function.Function which is | ||
// only available in Java8+. This is less efficient. The raciness is unimportant because this | ||
// is a cache | ||
V value = cache.getIfPresent(key); | ||
if (value == null) { | ||
value = mappingFunction.apply(key); | ||
|
||
cache.put(key, value); | ||
} | ||
return value; | ||
} | ||
|
||
@Override | ||
public void put(K key, V value) { | ||
cache.put(key, value); | ||
} | ||
} |
Oops, something went wrong.