Skip to content

[GR-50665] Make the snippet template cache global instead of per snippet. #11443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package jdk.graal.compiler.nodes.spi;

import java.util.BitSet;
import java.util.Map;

import jdk.graal.compiler.api.replacements.SnippetTemplateCache;
import jdk.graal.compiler.bytecode.BytecodeProvider;
Expand All @@ -38,6 +39,7 @@
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
import jdk.graal.compiler.options.OptionValues;
import jdk.graal.compiler.replacements.SnippetTemplate;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;

Expand Down Expand Up @@ -137,4 +139,9 @@ public <T extends SnippetTemplateCache> T getSnippetTemplateCache(Class<T> templ
public JavaKind getWordKind() {
return delegate.getWordKind();
}

@Override
public Map<SnippetTemplate.CacheKey, SnippetTemplate> getTemplatesCache() {
return delegate.getTemplatesCache();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package jdk.graal.compiler.nodes.spi;

import java.util.BitSet;
import java.util.Map;

import jdk.graal.compiler.api.replacements.Snippet;
import jdk.graal.compiler.api.replacements.SnippetTemplateCache;
Expand All @@ -39,6 +40,7 @@
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
import jdk.graal.compiler.options.OptionValues;
import jdk.graal.compiler.replacements.SnippetTemplate;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;

Expand All @@ -55,6 +57,12 @@ public interface Replacements extends GeneratedPluginInjectionProvider {
*/
GraphBuilderConfiguration.Plugins getGraphBuilderPlugins();

/**
* Least recently used cache for snippet templates. When a new element is added to this map, it evicts the least
* recently used element in case of full capacity.
*/
Map<SnippetTemplate.CacheKey, SnippetTemplate> getTemplatesCache();

/**
* Gets the plugin type that intrinsifies calls to {@code method}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import static jdk.graal.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;

import java.util.BitSet;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -111,6 +113,12 @@ public void setProviders(Providers providers) {
public final TargetDescription target;
protected GraphBuilderConfiguration.Plugins graphBuilderPlugins;
private final DebugHandlersFactory debugHandlersFactory;
private final Map<SnippetTemplate.CacheKey, SnippetTemplate> templatesCache;

@Override
public Map<SnippetTemplate.CacheKey, SnippetTemplate> getTemplatesCache() {
return templatesCache;
}

/**
* The preprocessed replacement graphs. This is keyed by a pair of a method and options because
Expand Down Expand Up @@ -242,6 +250,7 @@ public ReplacementsImpl(DebugHandlersFactory debugHandlersFactory, Providers pro
this.snippetTemplateCache = EconomicMap.create(Equivalence.DEFAULT);
this.defaultBytecodeProvider = bytecodeProvider;
this.debugHandlersFactory = debugHandlersFactory;
this.templatesCache = Collections.synchronizedMap(new SnippetTemplate.LRUCache<>());
}

private static final TimerKey SnippetPreparationTime = DebugContext.timer("SnippetPreparationTime");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

Expand Down Expand Up @@ -799,7 +798,7 @@ public ValueNode findLength(FindLengthMode mode, ConstantReflectionProvider cons
}
}

static class CacheKey {
public static class CacheKey {

private final ResolvedJavaMethod method;
private final Object[] values;
Expand Down Expand Up @@ -857,9 +856,6 @@ public int hashCode() {
public static class Options {
@Option(help = "Use a LRU cache for snippet templates.")//
public static final OptionKey<Boolean> UseSnippetTemplateCache = new OptionKey<>(true);

@Option(help = "")//
public static final OptionKey<Integer> MaxTemplatesPerSnippet = new OptionKey<>(50);
}

/**
Expand All @@ -869,20 +865,13 @@ public abstract static class AbstractTemplates implements SnippetTemplateCache {

protected final OptionValues options;
protected final SnippetReflectionProvider snippetReflection;
private final Map<CacheKey, SnippetTemplate> templates;

private final boolean shouldTrackNodeSourcePosition;

protected AbstractTemplates(OptionValues options, Providers providers) {
this.options = options;
this.snippetReflection = providers.getSnippetReflection();
this.shouldTrackNodeSourcePosition = providers.getCodeCache() != null && providers.getCodeCache().shouldDebugNonSafepoints();
if (Options.UseSnippetTemplateCache.getValue(options)) {
int size = Options.MaxTemplatesPerSnippet.getValue(options);
this.templates = Collections.synchronizedMap(new LRUCache<>(size, size));
} else {
this.templates = null;
}
}

public static ResolvedJavaMethod findMethod(MetaAccessProvider metaAccess, Class<?> declaringClass, String methodName) {
Expand Down Expand Up @@ -981,7 +970,7 @@ protected SnippetInfo snippet(Providers providers,
public SnippetTemplate template(CoreProviders context, ValueNode replacee, final Arguments args) {
StructuredGraph graph = replacee.graph();
DebugContext outer = graph.getDebug();
SnippetTemplate template = Options.UseSnippetTemplateCache.getValue(options) && args.cacheable ? templates.get(args.cacheKey) : null;
SnippetTemplate template = Options.UseSnippetTemplateCache.getValue(options) && args.cacheable ? context.getReplacements().getTemplatesCache().get(args.cacheKey) : null;
if (template == null || (graph.trackNodeSourcePosition() && !template.snippet.trackNodeSourcePosition())) {
try (DebugContext debug = context.getReplacements().openSnippetDebugContext("SnippetTemplate_", args.cacheKey.method, outer, options)) {
try (DebugCloseable a = SnippetTemplateCreationTime.start(outer);
Expand All @@ -1002,7 +991,7 @@ public SnippetTemplate template(CoreProviders context, ValueNode replacee, final
createMidTierPreLoweringPhases(),
createMidTierPostLoweringPhases());
if (Options.UseSnippetTemplateCache.getValue(snippetOptions) && args.cacheable) {
templates.put(args.cacheKey, template);
context.getReplacements().getTemplatesCache().put(args.cacheKey, template);
}
if (outer.areMetricsEnabled()) {
DebugContext.counter("SnippetTemplateNodeCount[%#s]", args).add(outer, template.nodes.size());
Expand Down Expand Up @@ -1037,11 +1026,21 @@ protected PhaseSuite<CoreProviders> createMidTierPostLoweringPhases() {

public static final class LRUCache<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;

/**
* Maximum capacity of the least-recently used snippet template cache. A higher number
* increases the total amount of memory used for snippet templates and a lower number
* increases the cache misses and thus decreases compilation speed. At a value of 64, the
* estimated misses are at 2% of lookups, at 80, they are at 1% of lookups, and at 100, they
* are at 0.5% of lookups.
*/
public static final int SNIPPET_CACHE_CAPACITY = 64;

private final int maxCacheSize;

public LRUCache(int initialCapacity, int maxCacheSize) {
super(initialCapacity, 0.75F, true);
this.maxCacheSize = maxCacheSize;
public LRUCache() {
super(SNIPPET_CACHE_CAPACITY, 0.75F, true);
this.maxCacheSize = SNIPPET_CACHE_CAPACITY;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,11 @@ static final class HashMapBuiltin extends Builtin {

HashMapBuiltin() {
super(HashMap.class, IdentityHashMap.class, LinkedHashMap.class, SnippetTemplate.LRUCache.class);
int size = SnippetTemplate.Options.MaxTemplatesPerSnippet.getDefaultValue();
factories = Map.of(
HashMap.class, HashMap::new,
IdentityHashMap.class, IdentityHashMap::new,
LinkedHashMap.class, LinkedHashMap::new,
SnippetTemplate.LRUCache.class, () -> new SnippetTemplate.LRUCache<>(size, size));
SnippetTemplate.LRUCache.class, SnippetTemplate.LRUCache::new);
}

@Override
Expand Down
Loading