changeset 11893:ec267141f753

more javadoc and output tweaks for dynamic counters
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 04 Oct 2013 11:56:18 +0200
parents 4ac39f060a9d
children c7abc8411011 992508ee13b6
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp
diffstat 8 files changed, 120 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Fri Oct 04 00:53:19 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Fri Oct 04 11:56:18 2013 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.HeapAccess.*;
 import com.oracle.graal.nodes.calc.*;
@@ -56,6 +57,26 @@
  * 
  * The subsystems that use the logging need to have their own options to turn on the counters, and
  * insert DynamicCounterNodes when they're enabled.
+ * 
+ * Counters will be displayed as a rate (per second) if their group name starts with "~", otherwise
+ * they will be displayed as a total number.
+ * 
+ * <h1>Example</h1> In order to create statistics about allocations within the DaCapo pmd benchmark
+ * the following steps are necessary:
+ * <ul>
+ * <li>Modify {@code thread.hpp}: increase GRAAL_COUNTER_SIZE. The actual required value depends on
+ * the granularity of the profiling, 10000 should be enough for most cases. This will increase the
+ * JavaThread structure by 80kb.</li>
+ * <li>Also in {@code thread.hpp}: GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS specifies whether the
+ * numbers generated by compiler threads should be excluded (default: true).</li>
+ * <li>Build the Graal VM.</li>
+ * <li>Start the DaCapo pmd benchmark with
+ * {@code "-G:BenchmarkDynamicCounters=err, starting ====, PASSED in "} and
+ * {@code -G:+ProfileAllocations}.</li>
+ * <li>The numbers will only include allocation from compiled code!</li>
+ * <li>The counters can be further configured by modifying the
+ * {@link NewObjectSnippets#PROFILE_MODE} field.</li>
+ * </ul>
  */
 public class BenchmarkCounters {
 
@@ -111,7 +132,7 @@
     }
 
     public static synchronized void dump(PrintStream out, double seconds, long[] counters) {
-        if (!staticCounters.isEmpty()) {
+        if (!groups.isEmpty()) {
             out.println("====== dynamic counters (" + staticCounters.size() + " in total) ======");
             for (String group : new TreeSet<>(groups)) {
                 if (group != null) {
@@ -159,7 +180,7 @@
             NumberFormat format = NumberFormat.getInstance(Locale.US);
             long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100);
             if (staticCounter) {
-                out.println("=========== " + group + " static counters: ");
+                out.println("=========== " + group + " (static counters):");
                 for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                     long counter = entry.getKey() / array.length;
                     if (counter >= cutoff) {
@@ -169,7 +190,16 @@
                 out.println(sum + ": total");
             } else {
                 if (group.startsWith("~")) {
-                    out.println("=========== " + group + " dynamic counters");
+                    out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:");
+                    for (Map.Entry<Long, String> entry : sorted.entrySet()) {
+                        long counter = entry.getKey() / array.length;
+                        if (counter >= cutoff) {
+                            out.println(format.format((long) (counter / seconds)) + "/s \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
+                        }
+                    }
+                    out.println(format.format((long) (sum / seconds)) + "/s: total");
+                } else {
+                    out.println("=========== " + group + " (dynamic counters):");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
                         if (counter >= cutoff) {
@@ -177,15 +207,6 @@
                         }
                     }
                     out.println(format.format(sum) + ": total");
-                } else {
-                    out.println("=========== " + group + " dynamic counters, time = " + seconds + " s");
-                    for (Map.Entry<Long, String> entry : sorted.entrySet()) {
-                        long counter = entry.getKey() / array.length;
-                        if (counter >= cutoff) {
-                            out.println(format.format((long) (counter / seconds)) + "/s \t" + ((counter * 200 + 1) / sum / 2) + "% \t" + entry.getValue());
-                        }
-                    }
-                    out.println(format.format((long) (sum / seconds)) + "/s: total");
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Oct 04 00:53:19 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Oct 04 11:56:18 2013 +0200
@@ -347,7 +347,7 @@
 
     private static void traceObject(boolean enabled, String action, Object object, boolean enter) {
         if (doProfile(action)) {
-            DynamicCounterNode.counter(action, enter ? "~monitorenter" : "~monitorexit", 1, PROFILE_CONTEXT);
+            DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT);
         }
         if (enabled) {
             Log.print(action);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Oct 04 00:53:19 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Oct 04 11:56:18 2013 +0200
@@ -122,8 +122,8 @@
             String name = createName(path, typeContext);
 
             boolean context = PROFILE_MODE == ProfileMode.AllocatingMethods || PROFILE_MODE == ProfileMode.AllocatedTypesInMethods;
-            DynamicCounterNode.counter(name, "~bytes", size, context);
-            DynamicCounterNode.counter(name, "~sites", 1, context);
+            DynamicCounterNode.counter(name, "number of bytes allocated", size, context);
+            DynamicCounterNode.counter(name, "number of allocations", 1, context);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/SurvivingCounterNode.java	Fri Oct 04 00:53:19 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * 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.graph.spi.*;
-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 group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) {
-        super(group, name, increment, addContext);
-        this.checkedValue = checkedValue;
-    }
-
-    @Override
-    public void simplify(SimplifierTool tool) {
-        if (checkedValue instanceof FloatingNode && checkedValue.usages().count() == 1) {
-            tool.addToWorkList(checkedValue);
-            graph().removeFixed(this);
-        }
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(checkedValue);
-        if (state != null && state.getState() == EscapeState.Virtual) {
-            tool.delete();
-        }
-    }
-
-    public static void addCounterBefore(String group, String name, long increment, boolean addContext, ValueNode checkedValue, FixedNode position) {
-        StructuredGraph graph = position.graph();
-        SurvivingCounterNode counter = graph.add(new SurvivingCounterNode(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue));
-        graph.addBeforeFixed(position, counter);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/WeakCounterNode.java	Fri Oct 04 11:56:18 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.graph.spi.*;
+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 WeakCounterNode extends DynamicCounterNode implements Simplifiable, Virtualizable {
+
+    @Input private ValueNode checkedValue;
+
+    public WeakCounterNode(String group, String name, ValueNode increment, boolean addContext, ValueNode checkedValue) {
+        super(group, name, increment, addContext);
+        this.checkedValue = checkedValue;
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        if (checkedValue instanceof FloatingNode && checkedValue.usages().count() == 1) {
+            tool.addToWorkList(checkedValue);
+            graph().removeFixed(this);
+        }
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(checkedValue);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            tool.delete();
+        }
+    }
+
+    public static void addCounterBefore(String group, String name, long increment, boolean addContext, ValueNode checkedValue, FixedNode position) {
+        StructuredGraph graph = position.graph();
+        WeakCounterNode counter = graph.add(new WeakCounterNode(name, group, ConstantNode.forLong(increment, graph), addContext, checkedValue));
+        graph.addBeforeFixed(position, counter);
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Fri Oct 04 00:53:19 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java	Fri Oct 04 11:56:18 2013 +0200
@@ -49,18 +49,18 @@
         });
     }
 
-    public void addSurvivingCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
+    public void addWeakCounterCounterBefore(final String group, final String name, final int increment, final boolean addContext, final ValueNode checkedValue, final FixedNode position) {
         add(new Effect() {
 
             @Override
             public String name() {
-                return "addSurvivingCounterBefore";
+                return "addWeakCounterBefore";
             }
 
             @Override
             public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
                 assert position.isAlive();
-                SurvivingCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position);
+                WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position);
             }
         });
     }
--- a/src/share/vm/runtime/thread.cpp	Fri Oct 04 00:53:19 2013 +0200
+++ b/src/share/vm/runtime/thread.cpp	Fri Oct 04 11:56:18 2013 +0200
@@ -1414,7 +1414,7 @@
 #ifdef GRAAL
 
 #if GRAAL_COUNTERS_SIZE > 0
-jlong JavaThread::_graal_old_counters[GRAAL_COUNTERS_SIZE];
+jlong JavaThread::_graal_old_thread_counters[GRAAL_COUNTERS_SIZE];
 
 bool graal_counters_include(oop threadObj) {
   return !GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS || threadObj == NULL || threadObj->klass() != SystemDictionary::CompilerThread_klass();
@@ -1423,7 +1423,7 @@
 void JavaThread::collect_counters(typeArrayOop array) {
   MutexLocker tl(Threads_lock);
   for (int i = 0; i < array->length(); i++) {
-    array->long_at_put(i, _graal_old_counters[i]);
+    array->long_at_put(i, _graal_old_thread_counters[i]);
   }
   for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
     if (graal_counters_include(tp->threadObj())) {
@@ -1479,10 +1479,12 @@
   _stack_guard_state = stack_guard_unused;
 #ifdef GRAAL
   _graal_alternate_call_target = NULL;
+#if GRAAL_COUNTERS_SIZE > 0
   for (int i = 0; i < GRAAL_COUNTERS_SIZE; i++) {
     _graal_counters[i] = 0;
   }
-#endif
+#endif // GRAAL_COUNTER_SIZE > 0
+#endif // GRAAL
   _exception_oop = NULL;
   _exception_pc  = 0;
   _exception_handler_pc = 0;
@@ -1675,7 +1677,7 @@
 #if defined(GRAAL) && (GRAAL_COUNTERS_SIZE > 0)
   if (graal_counters_include(threadObj())) {
     for (int i = 0; i < GRAAL_COUNTERS_SIZE; i++) {
-      _graal_old_counters[i] += _graal_counters[i];
+      _graal_old_thread_counters[i] += _graal_counters[i];
     }
   }
 #endif
--- a/src/share/vm/runtime/thread.hpp	Fri Oct 04 00:53:19 2013 +0200
+++ b/src/share/vm/runtime/thread.hpp	Fri Oct 04 11:56:18 2013 +0200
@@ -924,13 +924,15 @@
 #define GRAAL_COUNTERS_SIZE (0)
 #define GRAAL_COUNTERS_EXCLUDE_COMPILER_THREADS (true)
 
+#if GRAAL_COUNTERS_SIZE > 0
   jlong     _graal_counters[GRAAL_COUNTERS_SIZE];
-  static jlong _graal_old_counters[GRAAL_COUNTERS_SIZE];
+  static jlong _graal_old_thread_counters[GRAAL_COUNTERS_SIZE];
+#endif // GRAAL_COUNTERS_SIZE > 0
 
  public:
   static void collect_counters(typeArrayOop array);
  private:
-#endif
+#endif // GRAAL
   StackGuardState        _stack_guard_state;
 
   nmethod*      _scanned_nmethod;  // nmethod being scanned by the sweeper
@@ -1390,8 +1392,12 @@
 #ifdef GRAAL
   static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); }
   static ByteSize graal_implicit_exception_pc_offset() { return byte_offset_of(JavaThread, _graal_implicit_exception_pc); }
-  static ByteSize graal_counters_offset()              { return byte_offset_of(JavaThread, _graal_counters             ); }
-#endif
+#if GRAAL_COUNTERS_SIZE > 0
+  static ByteSize graal_counters_offset()        { return byte_offset_of(JavaThread, _graal_counters      ); }
+#else
+  static ByteSize graal_counters_offset()        { return in_ByteSize(0); }
+#endif // GRAAL_COUNTERS_SIZE > 0
+#endif // GRAAL
   static ByteSize exception_oop_offset()         { return byte_offset_of(JavaThread, _exception_oop       ); }
   static ByteSize exception_pc_offset()          { return byte_offset_of(JavaThread, _exception_pc        ); }
   static ByteSize exception_handler_pc_offset()  { return byte_offset_of(JavaThread, _exception_handler_pc); }