# HG changeset patch # User Lukas Stadler # Date 1364206180 -3600 # Node ID ca29d921a53aad695847f7d0d21419e12ef78755 # Parent f94baf373bcf18d5133fa2fd54c836379a2c7ddf GraalOptions.BenchmarkDynamicCounters to get counters for dacapo/specjvm2008 run diff -r f94baf373bcf -r ca29d921a53a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Mar 21 13:35:45 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Mar 25 11:09:40 2013 +0100 @@ -44,6 +44,7 @@ import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.debug.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.printer.*; @@ -76,6 +77,8 @@ private boolean quietMeterAndTime; + private long compilerStartTime; + public VMToCompilerImpl(HotSpotGraalRuntime compiler) { this.graalRuntime = compiler; @@ -196,6 +199,95 @@ t.setDaemon(true); t.start(); } + + if (GraalOptions.BenchmarkDynamicCounters) { + System.setErr(new PrintStream(new BenchmarkCountersOutputStream(System.err, " starting =====", " PASSED in ", "\n"))); + System.setOut(new PrintStream(new BenchmarkCountersOutputStream(System.out, "Iteration ~ (~s) begins: ", "Iteration ~ (~s) ends: ", "\n"))); + DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/"; + DynamicCounterNode.enabled = true; + } + if (GraalOptions.GenericDynamicCounters) { + DynamicCounterNode.enabled = true; + } + compilerStartTime = System.nanoTime(); + } + + private final class BenchmarkCountersOutputStream extends CallbackOutputStream { + + private long startTime; + private boolean waitingForEnd; + + private BenchmarkCountersOutputStream(PrintStream delegate, String... patterns) { + super(delegate, patterns); + } + + @Override + protected void patternFound(int index) { + switch (index) { + case 0: + startTime = System.nanoTime(); + DynamicCounterNode.clear(); + break; + case 1: + waitingForEnd = true; + break; + case 2: + if (waitingForEnd) { + waitingForEnd = false; + DynamicCounterNode.dump(delegate, (System.nanoTime() - startTime) / 1000000000d); + } + break; + } + } + } + + public abstract static class CallbackOutputStream extends OutputStream { + + protected final PrintStream delegate; + private final byte[][] patterns; + private final int[] positions; + + public CallbackOutputStream(PrintStream delegate, String... patterns) { + this.delegate = delegate; + this.positions = new int[patterns.length]; + this.patterns = new byte[patterns.length][]; + for (int i = 0; i < patterns.length; i++) { + this.patterns[i] = patterns[i].getBytes(); + } + } + + protected abstract void patternFound(int index); + + @Override + public void write(int b) throws IOException { + try { + delegate.write(b); + for (int i = 0; i < patterns.length; i++) { + int j = positions[i]; + byte[] cs = patterns[i]; + byte patternChar = cs[j]; + if (patternChar == '~' && Character.isDigit(b)) { + // nothing to do... + } else { + if (patternChar == '~') { + patternChar = cs[++positions[i]]; + } + if (b == patternChar) { + positions[i]++; + } else { + positions[i] = 0; + } + } + if (positions[i] == patterns[i].length) { + positions[i] = 0; + patternFound(i); + } + } + } catch (RuntimeException e) { + e.printStackTrace(delegate); + throw e; + } + } } /** @@ -281,6 +373,7 @@ } System.gc(); phaseTransition("bootstrap2"); + } private MetricRateInPhase parsedBytecodesPerSecond; @@ -353,6 +446,9 @@ } SnippetCounter.printGroups(TTY.out().out()); + if (GraalOptions.GenericDynamicCounters) { + DynamicCounterNode.dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d); + } } private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { diff -r f94baf373bcf -r ca29d921a53a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Thu Mar 21 13:35:45 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Mon Mar 25 11:09:40 2013 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.debug; +import java.io.*; import java.util.*; import com.oracle.graal.api.meta.*; @@ -45,30 +46,39 @@ private static final int MAX_COUNTERS = 10 * 1024; private static final long[] COUNTERS = new long[MAX_COUNTERS]; private static final HashMap INDEXES = new HashMap<>(); + public static String excludedClassPrefix = null; + public static boolean enabled = false; + private final String name; private final long increment; private final boolean addContext; public DynamicCounterNode(String name, long increment, boolean addContext) { super(StampFactory.forVoid()); + if (!enabled) { + throw new GraalInternalError("dynamic counters not enabled"); + } this.name = name; this.increment = increment; this.addContext = addContext; } + public String getName() { + return name; + } + + public long getIncrement() { + return increment; + } + + public boolean isAddContext() { + return addContext; + } + private static synchronized int getIndex(String name) { Integer index = INDEXES.get(name); if (index == null) { index = INDEXES.size(); - if (index == 0) { - Runtime.getRuntime().addShutdownHook(new Thread() { - - @Override - public void run() { - dump(); - } - }); - } INDEXES.put(name, index); if (index >= MAX_COUNTERS) { throw new GraalInternalError("too many dynamic counters"); @@ -79,44 +89,59 @@ } } - private static synchronized void dump() { + public static synchronized void dump(PrintStream out, double seconds) { TreeMap sorted = new TreeMap<>(); long sum = 0; for (int i = 0; i < MAX_COUNTERS; i++) { sum += COUNTERS[i]; } + long cutoff = sum / 1000; int cnt = 0; for (Map.Entry entry : INDEXES.entrySet()) { - sorted.put(COUNTERS[entry.getValue()] * MAX_COUNTERS + cnt++, entry.getKey()); + if (COUNTERS[entry.getValue()] > cutoff) { + sorted.put(COUNTERS[entry.getValue()] * MAX_COUNTERS + cnt++, entry.getKey()); + } } + out.println("=========== dynamic counters, time = " + seconds + " s"); for (Map.Entry entry : sorted.entrySet()) { - System.out.println((entry.getKey() / MAX_COUNTERS) + ": " + entry.getValue()); + long counter = entry.getKey() / MAX_COUNTERS; + out.println((int) (counter / seconds) + "/s \t" + (counter * 100 / sum) + "% \t" + entry.getValue()); } - System.out.println(sum + ": total"); + out.println((int) (sum / seconds) + "/s: total"); + out.println("============================"); + clear(); + } + + public static void clear() { + Arrays.fill(COUNTERS, 0); } @Override public void lower(LoweringTool tool) { - int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name); + StructuredGraph graph = (StructuredGraph) graph(); + if (excludedClassPrefix == null || !graph.method().getDeclaringClass().getName().startsWith(excludedClassPrefix)) { + int index = addContext ? getIndex(name + " @ " + MetaUtil.format("%h.%n", ((StructuredGraph) graph()).method())) : getIndex(name); - StructuredGraph graph = (StructuredGraph) graph(); - ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, tool.getRuntime(), graph); - ConstantNode indexConstant = ConstantNode.forInt(index, graph); - LoadIndexedNode load = graph.add(new LoadIndexedNode(arrayConstant, indexConstant, Kind.Long)); - IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, load, ConstantNode.forLong(increment, graph))); - StoreIndexedNode store = graph.add(new StoreIndexedNode(arrayConstant, indexConstant, Kind.Long, add)); + ConstantNode arrayConstant = ConstantNode.forObject(COUNTERS, tool.getRuntime(), graph); + ConstantNode indexConstant = ConstantNode.forInt(index, graph); + LoadIndexedNode load = graph.add(new LoadIndexedNode(arrayConstant, indexConstant, Kind.Long)); + IntegerAddNode add = graph.add(new IntegerAddNode(Kind.Long, load, ConstantNode.forLong(increment, graph))); + StoreIndexedNode store = graph.add(new StoreIndexedNode(arrayConstant, indexConstant, Kind.Long, add)); - graph.addBeforeFixed(this, load); - graph.addBeforeFixed(this, store); + graph.addBeforeFixed(this, load); + graph.addBeforeFixed(this, store); + } graph.removeFixed(this); } - public static void createCounter(String name, FixedNode before, long increment, boolean addContext) { - StructuredGraph graph = (StructuredGraph) before.graph(); - DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, increment, addContext)); - graph.addBeforeFixed(before, counter); + public static void addCounterBefore(String name, long increment, boolean addContext, FixedNode position) { + if (enabled) { + StructuredGraph graph = (StructuredGraph) position.graph(); + DynamicCounterNode counter = graph.add(new DynamicCounterNode(name, increment, addContext)); + graph.addBeforeFixed(position, counter); + } } } diff -r f94baf373bcf -r ca29d921a53a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java Mon Mar 25 11:09:40 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, 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.nodes.debug; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * This is a special version of the dynamic counter node that removes itself as soon as it's the + * only usage of the associated node. This way it only increments the counter if the node is + * actually executed. + */ +public class SurvivingCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable { + + @Input private ValueNode checkedValue; + + public SurvivingCounterNode(String name, long increment, boolean addContext, ValueNode checkedValue) { + super(name, increment, addContext); + this.checkedValue = checkedValue; + } + + @Override + public void simplify(SimplifierTool tool) { + if (checkedValue instanceof FloatingNode && checkedValue.usages().count() == 1) { + tool.addToWorkList(checkedValue); + ((StructuredGraph) graph()).removeFixed(this); + // ((StructuredGraph) graph()).replaceFixedWithFixed(this, graph().add(new + // DynamicCounterNode("non-surviving " + getName(), getIncrement(), isAddContext()))); + } + } + + @Override + public void virtualize(VirtualizerTool tool) { + State state = tool.getObjectState(checkedValue); + if (state != null && state.getState() == EscapeState.Virtual) { + tool.delete(); + } + } +} diff -r f94baf373bcf -r ca29d921a53a graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Mar 21 13:35:45 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Mar 25 11:09:40 2013 +0100 @@ -124,6 +124,8 @@ public static String LogFile = null; public static String MethodFilter = null; public static boolean DumpOnError = ____; + public static boolean GenericDynamicCounters = ____; + public static boolean BenchmarkDynamicCounters = ____; // Ideal graph visualizer output settings public static boolean PrintBinaryGraphs = true;