Skip to content

Commit

Permalink
[GR-37247] Reduce memory footprint.
Browse files Browse the repository at this point in the history
PullRequest: graal/11378
  • Loading branch information
Christian Wimmer committed Mar 25, 2022
2 parents 039edd0 + 8360033 commit 54db64f
Show file tree
Hide file tree
Showing 18 changed files with 138 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,15 @@ public void copy(Node fromNode, Node toNode) {
}
}

void minimizeSize(Node node) {
for (int i = getDirectCount(); i < getCount(); i++) {
NodeList<Node> list = getNodeList(node, offsets, i);
if (list != null) {
list.minimizeSize();
}
}
}

/**
* Sets the value of a given edge without notifying the new and old nodes on the other end of
* the edge of the change.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -948,15 +948,31 @@ protected void afterNodeIdChange(Node node, Object value) {
* of nodes is compressed such that all non-null entries precede all null entries while
* preserving the ordering between the nodes within the list.
*/
public boolean maybeCompress() {
if (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()) {
public final boolean maybeCompress() {
return compress(false);
}

/**
* Minimize the memory occupied by the graph by trimming all node arrays to the minimum size.
* Note that this can make subsequent optimization phases run slower, because additions to the
* graph must re-allocate larger arrays again. So invoking this method is only beneficial if a
* graph is alive for a long time.
*/
public final void minimizeSize() {
compress(true);
}

protected boolean compress(boolean minimizeSize) {
if (!minimizeSize && (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod())) {
return false;
}
int liveNodeCount = getNodeCount();
int liveNodePercent = liveNodeCount * 100 / nodesSize;
int compressionThreshold = Options.GraphCompressionThreshold.getValue(options);
if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) {
return false;
if (!minimizeSize) {
int liveNodePercent = liveNodeCount * 100 / nodesSize;
int compressionThreshold = Options.GraphCompressionThreshold.getValue(options);
if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) {
return false;
}
}
GraphCompressions.increment(debug);
int nextId = 0;
Expand Down Expand Up @@ -984,9 +1000,38 @@ public boolean maybeCompress() {
compressions++;
nodesDeletedBeforeLastCompression += nodesDeletedSinceLastCompression;
nodesDeletedSinceLastCompression = 0;

if (minimizeSize) {
/* Trim the array of all alive nodes itself. */
nodes = trimArrayToNewSize(nodes, nextId, NodeList.EMPTY_NODE_ARRAY);
/* Remove deleted nodes from the linked list of Node.typeCacheNext. */
recomputeIterableNodeLists();
/* Trim node arrays used within each node. */
for (Node node : nodes) {
node.extraUsages = trimArrayToNewSize(node.extraUsages, node.extraUsagesCount, NodeList.EMPTY_NODE_ARRAY);
node.getNodeClass().getInputEdges().minimizeSize(node);
node.getNodeClass().getSuccessorEdges().minimizeSize(node);
}
}
return true;
}

static <T> T[] trimArrayToNewSize(T[] input, int newSize, T[] emptyArray) {
assert emptyArray.length == 0;
if (input.length == newSize) {
return input;
}
for (int i = newSize; i < input.length; i++) {
GraalError.guarantee(input[i] == null, "removing non-null element");
}

if (newSize == 0) {
return emptyArray;
} else {
return Arrays.copyOf(input, newSize);
}
}

/**
* Returns an {@link Iterable} providing all the live nodes whose type is compatible with
* {@code type}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,11 @@ protected NodeList(Node self, int initialSize) {
checkMaxSize(initialSize);
this.size = initialSize;
this.initialSize = initialSize;
this.nodes = new Node[initialSize];
if (initialSize == 0) {
this.nodes = EMPTY_NODE_ARRAY;
} else {
this.nodes = new Node[initialSize];
}
}

protected NodeList(Node self, T[] elements) {
Expand Down Expand Up @@ -232,8 +236,13 @@ public void initialize(int index, Node node) {
void copy(NodeList<? extends Node> other) {
self.incModCount();
incModCount();
Node[] newNodes = new Node[other.size];
System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length);
Node[] newNodes;
if (other.size == 0) {
newNodes = EMPTY_NODE_ARRAY;
} else {
newNodes = new Node[other.size];
System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length);
}
nodes = newNodes;
size = other.size;
}
Expand Down Expand Up @@ -279,6 +288,10 @@ void clearWithoutUpdate() {
size = 0;
}

void minimizeSize() {
nodes = Graph.trimArrayToNewSize(nodes, size, EMPTY_NODE_ARRAY);
}

@Override
@SuppressWarnings("unchecked")
public boolean remove(Object node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ protected final StructuredGraph getGraph(DebugContext debug, CompilationIdentifi
ResolvedJavaMethod getAndClearObjectResult = foreignCallSnippets.getAndClearObjectResult.getMethod();
ResolvedJavaMethod verifyObject = foreignCallSnippets.verifyObject.getMethod();
ResolvedJavaMethod thisMethod = getGraphMethod();
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString(), false);
GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString(), false, true);
StructuredGraph graph = kit.getGraph();
graph.disableFrameStateVerification();
ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,8 +560,8 @@ protected void afterNodeIdChange(Node node, Object value) {
}

@Override
public boolean maybeCompress() {
if (super.maybeCompress()) {
protected boolean compress(boolean minimizeSize) {
if (super.compress(minimizeSize)) {
/*
* The schedule contains a NodeMap which is unusable after compression.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ protected abstract static class Structure {
}

public GraphKit(DebugContext debug, ResolvedJavaMethod stubMethod, Providers providers, WordTypes wordTypes, Plugins graphBuilderPlugins, CompilationIdentifier compilationId, String name,
boolean trackNodeSourcePosition) {
boolean trackNodeSourcePosition, boolean recordInlinedMethods) {
super(providers);
StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).compilationId(compilationId).profileProvider(null);
StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).recordInlinedMethods(recordInlinedMethods).compilationId(compilationId).profileProvider(null);
if (name != null) {
builder.name(name);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ public static AnalysisParsedGraph parseBytecode(BigBang bb, AnalysisMethod metho
return EMPTY;
}

graph = new StructuredGraph.Builder(options, debug).method(method).build();
graph = new StructuredGraph.Builder(options, debug)
.method(method)
.recordInlinedMethods(false)
.build();
try (DebugContext.Scope s = debug.scope("ClosedWorldAnalysis", graph, method)) {

// enable this logging to get log output in compilation passes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ private boolean parse() {
* needed after static analysis.
*/
if (bb.strengthenGraalGraphs()) {
graph.minimizeSize();
method.setAnalyzedGraph(graph);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private enum State {
private final AtomicReference<State> state;
private final LongAdder postedOperations;
private final LongAdder completedOperations;
private final List<DebugContextRunnable> postedBeforeStart;
private List<DebugContextRunnable> postedBeforeStart;
private final CopyOnWriteArrayList<Throwable> exceptions = new CopyOnWriteArrayList<>();

private ExecutorService executorService;
Expand Down Expand Up @@ -90,7 +90,6 @@ public CompletionExecutor(BigBang bb, ForkJoinPool forkJoin, Runnable heartbeatC
state = new AtomicReference<>(State.UNUSED);
postedOperations = new LongAdder();
completedOperations = new LongAdder();
postedBeforeStart = new ArrayList<>();
startingThread = Thread.currentThread();
}

Expand All @@ -103,7 +102,7 @@ public void init(Timing newTiming) {
setState(State.BEFORE_START);
postedOperations.reset();
completedOperations.reset();
postedBeforeStart.clear();
postedBeforeStart = new ArrayList<>();
vmConfig = bb.getHostVM().getConfiguration();
}

Expand Down Expand Up @@ -213,7 +212,7 @@ public void start() {

setState(State.STARTED);
postedBeforeStart.forEach(this::execute);
postedBeforeStart.clear();
postedBeforeStart = null;
}

private void setState(State newState) {
Expand Down Expand Up @@ -271,7 +270,7 @@ public long complete() throws InterruptedException {
}

public long getPostedOperations() {
return postedOperations.sum() + postedBeforeStart.size();
return postedOperations.sum() + (postedBeforeStart == null ? 0 : postedBeforeStart.size());
}

public boolean isSequential() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,12 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod

EncodedGraph encodedGraph = new EncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, null, null, false, trackNodeSourcePosition);
try (DebugContext debug = openSnippetDebugContext("SVMSnippet_", method, options)) {
StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).trackNodeSourcePosition(trackNodeSourcePosition).setIsSubstitution(true).build();
StructuredGraph result = new StructuredGraph.Builder(options, debug)
.method(method)
.trackNodeSourcePosition(trackNodeSourcePosition)
.recordInlinedMethods(false)
.setIsSubstitution(true)
.build();
PEGraphDecoder graphDecoder = new PEGraphDecoder(ConfigurationValues.getTarget().arch, result, providers, null, snippetInvocationPlugins, new InlineInvokePlugin[0], parameterPlugin, null,
null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), true) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public class SubstrateGraphKit extends GraphKit {

public SubstrateGraphKit(DebugContext debug, ResolvedJavaMethod stubMethod, Providers providers, WordTypes wordTypes, GraphBuilderConfiguration.Plugins graphBuilderPlugins,
CompilationIdentifier compilationId) {
super(debug, stubMethod, providers, wordTypes, graphBuilderPlugins, compilationId, null, SubstrateOptions.parseOnce());
super(debug, stubMethod, providers, wordTypes, graphBuilderPlugins, compilationId, null, SubstrateOptions.parseOnce(), false);
assert wordTypes != null : "Support for Word types is mandatory";
frameState = new FrameStateBuilder(this, stubMethod, graph);
frameState.disableKindVerification();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,13 @@ public static StructuredGraph decodeGraph(DebugContext debug, String name, Compi
}

boolean isSubstitution = method.getAnnotation(Snippet.class) != null;
StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug).name(name).method(method).compilationId(compilationId).setIsSubstitution(isSubstitution).build();
StructuredGraph graph = new StructuredGraph.Builder(debug.getOptions(), debug)
.name(name)
.method(method)
.recordInlinedMethods(false)
.compilationId(compilationId)
.setIsSubstitution(isSubstitution)
.build();
GraphDecoder decoder = new GraphDecoder(ConfigurationValues.getTarget().arch, graph);
decoder.decode(encodedGraph);
return graph;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,10 @@ private void processMethod(CallTreeNode node, Deque<CallTreeNode> worklist, BigB
return;
}
parse = true;
graph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES).method(method).build();
graph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES)
.method(method)
.recordInlinedMethods(false)
.build();
}

try (DebugContext.Scope scope = debug.scope("RuntimeCompile", graph)) {
Expand Down Expand Up @@ -730,6 +733,9 @@ public void beforeCompilation(BeforeCompilationAccess c) {
GraalSupport.setGraphEncoding(config, graphEncoder.getEncoding(), graphEncoder.getObjects(), graphEncoder.getNodeClasses());

objectReplacer.updateDataDuringAnalysis();

/* All the temporary data structures used during encoding are no longer necessary. */
graphEncoder = null;
}

private static void removeUnreachableInvokes(CallTreeNode node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ private boolean canInitializeWithoutSideEffects(ResolvedJavaMethod clinit, Set<C

GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);

StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(clinit).build();
StructuredGraph graph = new StructuredGraph.Builder(options, debug)
.method(clinit)
.recordInlinedMethods(false)
.build();
graph.setGuardsStage(GuardsStage.FIXED_DEOPTS);
GraphBuilderPhase.Instance builderPhase = new ClassInitializerGraphBuilderPhase(context, graphBuilderConfig, context.getOptimisticOptimizations());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ public interface CompileFunction {

private SnippetReflectionProvider snippetReflection;
private final FeatureHandler featureHandler;
private final OptionValues compileOptions;

private volatile boolean inliningProgress;

Expand Down Expand Up @@ -391,6 +392,7 @@ public CompileQueue(DebugContext debug, FeatureHandler featureHandler, HostedUni
this.executor = new CompletionExecutor(universe.getBigBang(), executorService, universe.getBigBang().getHeartbeatCallback());
this.featureHandler = featureHandler;
this.snippetReflection = snippetReflection;
this.compileOptions = getCustomizedOptions(debug);

callForReplacements(debug, runtimeConfig);
}
Expand Down Expand Up @@ -689,6 +691,7 @@ private void doInlineTrivial(DebugContext debug, final HostedMethod method) {
* Publish the new graph, it can be picked up immediately by other threads
* trying to inline this method.
*/
graph.minimizeSize();
method.compilationInfo.setGraph(graph);
checkTrivial(method);
inliningProgress = true;
Expand Down Expand Up @@ -835,13 +838,12 @@ private StructuredGraph transplantGraph(DebugContext debug, HostedMethod hMethod
*/
aMethod.setAnalyzedGraph(null);

OptionValues options = getCustomizedOptions(debug);
/*
* The static analysis always needs NodeSourcePosition. But for AOT compilation, we only
* need to preserve them when explicitly enabled, to reduce memory pressure.
*/
boolean trackNodeSourcePosition = GraalOptions.TrackNodeSourcePosition.getValue(options);
StructuredGraph graph = aGraph.copy(universe.lookup(aGraph.method()), options, debug, trackNodeSourcePosition);
boolean trackNodeSourcePosition = GraalOptions.TrackNodeSourcePosition.getValue(compileOptions);
StructuredGraph graph = aGraph.copy(universe.lookup(aGraph.method()), compileOptions, debug, trackNodeSourcePosition);

transplantEscapeAnalysisState(graph);

Expand Down Expand Up @@ -1077,7 +1079,7 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi
Bytecode code = new ResolvedJavaMethodBytecode(method);
// DebugContext debug = new DebugContext(options,
// providers.getSnippetReflection());
graph = new SubstrateIntrinsicGraphBuilder(getCustomizedOptions(debug), debug, providers,
graph = new SubstrateIntrinsicGraphBuilder(compileOptions, debug, providers,
code).buildGraph(plugin);
}
}
Expand All @@ -1087,7 +1089,10 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi
}
if (graph == null) {
needParsing = true;
graph = new StructuredGraph.Builder(getCustomizedOptions(debug), debug).method(method).build();
graph = new StructuredGraph.Builder(compileOptions, debug)
.method(method)
.recordInlinedMethods(false)
.build();
}
}
try (DebugContext.Scope s = debug.scope("Parsing", graph, method, this)) {
Expand All @@ -1107,6 +1112,7 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi
afterParseSuite.apply(method.compilationInfo.graph, new HighTierContext(providers, afterParseSuite, getOptimisticOpts()));
assert GraphOrder.assertSchedulableGraph(method.compilationInfo.getGraph());

graph.minimizeSize();
method.compilationInfo.numNodesAfterParsing = graph.getNodeCount();
if (!parseOnce) {
UninterruptibleAnnotationChecker.checkAfterParsing(method, graph);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,10 @@ private boolean processInvokeWithMethodHandle(GraphBuilderContext b, Replacement
GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(parsingProviders, graphBuilderConfig, OptimisticOptimizations.NONE, null);

DebugContext debug = b.getDebug();
StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(NativeImageUtil.toOriginal(methodHandleMethod)).build();
StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug)
.method(NativeImageUtil.toOriginal(methodHandleMethod))
.recordInlinedMethods(false)
.build();
try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
graphBuilder.apply(graph);
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,10 @@ private boolean isAliased(ResolvedJavaType type) {
private StructuredGraph getStaticInitializerGraph(ResolvedJavaMethod clinit, OptionValues options, DebugContext debug) {
assert clinit.hasBytecodes();

StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(clinit).build();
StructuredGraph graph = new StructuredGraph.Builder(options, debug)
.method(clinit)
.recordInlinedMethods(false)
.build();
HighTierContext context = new HighTierContext(GraalAccess.getOriginalProviders(), null, OptimisticOptimizations.NONE);
graph.setGuardsStage(GuardsStage.FIXED_DEOPTS);

Expand Down
Loading

0 comments on commit 54db64f

Please sign in to comment.