Mercurial > hg > graal-compiler
changeset 19926:575d7607f827
Truffle: implemented new -G:+PrintTruffleExpansionHistogram tool.
author | Christian Humer <christian.humer@oracle.com> |
---|---|
date | Wed, 18 Mar 2015 02:15:37 +0100 |
parents | 72afcc30c4a0 |
children | 517cbecdc20f b6af1acf00d6 5119e7f07d93 |
files | graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java |
diffstat | 3 files changed, 190 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 18 02:17:34 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Mar 18 02:15:37 2015 +0100 @@ -319,11 +319,18 @@ plugins.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); plugins.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy())); - plugins.setInlineInvokePlugin(new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements())); + InlineInvokePlugin inlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements()); + if (PrintTruffleExpansionHistogram.getValue()) { + inlinePlugin = new HistogramInlineInvokePlugin(graph, inlinePlugin); + } + plugins.setInlineInvokePlugin(inlinePlugin); plugins.setLoopExplosionPlugin(new PELoopExplosionPlugin()); InvocationPlugins invocationPlugins = newConfig.getPlugins().getInvocationPlugins(); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig, TruffleCompilerImpl.Optimizations, null).apply(graph); + if (PrintTruffleExpansionHistogram.getValue()) { + ((HistogramInlineInvokePlugin) inlinePlugin).print(callTarget, System.out); + } Debug.dump(graph, "After FastPE"); // Perform deoptimize to guard conversion.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Mar 18 02:17:34 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Mar 18 02:15:37 2015 +0100 @@ -156,6 +156,9 @@ @Option(help = "Print source secions for printed expansion trees", type = OptionType.Debug) public static final OptionValue<Boolean> TraceTruffleExpansionSource = new OptionValue<>(false); + @Option(help = "Prints a histogram of all expanded Java methods.", type = OptionType.Debug) + public static final OptionValue<Boolean> PrintTruffleExpansionHistogram = new OptionValue<>(false); + @Option(help = "Print detailed information for the Truffle compilation cache", type = OptionType.Debug) public static final OptionValue<Boolean> TraceTruffleCacheDetails = new OptionValue<>(false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java Wed Mar 18 02:15:37 2015 +0100 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.debug; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graphbuilderconf.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.truffle.*; + +public class HistogramInlineInvokePlugin implements InlineInvokePlugin { + + private final Map<ResolvedJavaMethod, MethodStatistics> histogram = new HashMap<>(); + private final StructuredGraph graph; + private final InlineInvokePlugin delegate; + + private HistogramInlineInvokePlugin.MethodStatistic currentStatistic; + + public HistogramInlineInvokePlugin(StructuredGraph graph, InlineInvokePlugin delegate) { + this.graph = graph; + this.delegate = delegate; + } + + public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + InlineInfo inlineInfo = delegate.getInlineInfo(b, method, args, returnType); + if (inlineInfo != null) { + currentStatistic = new MethodStatistic(currentStatistic, inlineInfo.methodToInline, graph.getNodeCount(), graph.getNodes(MethodCallTargetNode.TYPE).count()); + } + return inlineInfo; + } + + public void postInline(ResolvedJavaMethod inlinedTargetMethod) { + delegate.postInline(inlinedTargetMethod); + + if (currentStatistic != null) { + currentStatistic.applyNodeCountAfter(graph.getNodeCount()); + currentStatistic.applyCallsAfter(graph.getNodes(MethodCallTargetNode.TYPE).count()); + accept(currentStatistic); + currentStatistic = currentStatistic.getParent(); + } + } + + private void accept(MethodStatistic current) { + ResolvedJavaMethod method = current.getMethod(); + HistogramInlineInvokePlugin.MethodStatistics statistics = histogram.get(method); + if (statistics == null) { + statistics = new MethodStatistics(method); + histogram.put(method, statistics); + } + statistics.accept(current); + } + + public void print(OptimizedCallTarget target, PrintStream out) { + out.printf("Truffle expansion histogram for %s", target); + out.println(" Invocations = Number of expanded invocations"); + out.println(" Nodes = Number of Graal nodes created for this method during partial evaluation."); + out.println(" Calls = Number of not expanded calls created for this method during partial evaluation."); + out.printf(" %-11s |Nodes %5s %5s %5s %8s |Calls %5s %5s %5s %8s | Method Name%n", "Invocations", "Sum", "Min", "Max", "Avg", "Sum", "Min", "Max", "Avg"); + histogram.values().stream().sorted().forEach(statistics -> statistics.print(out)); + } + + private static class MethodStatistics implements Comparable<MethodStatistics> { + + private final ResolvedJavaMethod method; + + private int count; + private final IntSummaryStatistics shallowCount = new IntSummaryStatistics(); + private final IntSummaryStatistics callCount = new IntSummaryStatistics(); + + public MethodStatistics(ResolvedJavaMethod method) { + this.method = method; + } + + public void print(PrintStream out) { + out.printf(" %11d | %5d %5d %5d %8.2f | %5d %5d %5d %8.2f | %s%n", // + count, shallowCount.getSum(), shallowCount.getMin(), shallowCount.getMax(), // + shallowCount.getAverage(), callCount.getSum(), callCount.getMin(), callCount.getMax(), // + callCount.getAverage(), method.format("%h.%n(%p)")); + } + + public int compareTo(MethodStatistics o) { + int result = (int) (o.shallowCount.getSum() - shallowCount.getSum()); + if (result == 0) { + return o.count - count; + } + return result; + } + + public void accept(MethodStatistic statistic) { + if (!statistic.method.equals(method)) { + throw new IllegalArgumentException("invalid statistic"); + } + count++; + callCount.accept(statistic.getShallowCallCount()); + shallowCount.accept(statistic.getShallowNodeCount()); + } + } + + private static class MethodStatistic { + + private final MethodStatistic parent; + private final List<MethodStatistic> children = new ArrayList<>(); + + private final ResolvedJavaMethod method; + private int deepNodeCount; + private int callCount; + + public MethodStatistic(MethodStatistic parent, ResolvedJavaMethod method, int nodeCountBefore, int callsBefore) { + this.parent = parent; + this.method = method; + this.callCount = callsBefore; + this.deepNodeCount = nodeCountBefore; + if (parent != null) { + this.parent.getChildren().add(this); + } + } + + public ResolvedJavaMethod getMethod() { + return method; + } + + public List<MethodStatistic> getChildren() { + return children; + } + + public int getShallowNodeCount() { + int shallowCount = deepNodeCount; + for (MethodStatistic child : children) { + shallowCount -= child.deepNodeCount; + } + return shallowCount; + } + + public int getShallowCallCount() { + int shallowCount = callCount; + for (MethodStatistic child : children) { + shallowCount -= child.callCount; + } + return shallowCount; + } + + public void applyNodeCountAfter(int nodeCountAfter) { + deepNodeCount = nodeCountAfter - this.deepNodeCount; + } + + public void applyCallsAfter(int callsAfter) { + callCount = callsAfter - this.callCount; + } + + public MethodStatistic getParent() { + return parent; + } + + } + +}