From 625ac5006e7bc58214bb22065d8551e23f25c26f Mon Sep 17 00:00:00 2001 From: mchung Date: Mon, 14 Sep 2009 13:37:26 -0700 Subject: [PATCH] 6878481: Add performance counters in the JDK Summary: Added new performance counters in the JDK to track performance metrics Reviewed-by: alanb, dholmes, iris, forax, andrew --- make/java/java/FILES_java.gmk | 4 +- src/share/classes/java/lang/ClassLoader.java | 7 + .../classes/java/net/URLClassLoader.java | 3 + src/share/classes/java/util/zip/ZipFile.java | 3 + src/share/classes/sun/misc/PerfCounter.java | 191 ++++++++++++++++++ .../sun/java2d/d3d/D3DGraphicsDevice.java | 3 + 6 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/share/classes/sun/misc/PerfCounter.java diff --git a/make/java/java/FILES_java.gmk b/make/java/java/FILES_java.gmk index e8a2223f6..2ad599cbe 100644 --- a/make/java/java/FILES_java.gmk +++ b/make/java/java/FILES_java.gmk @@ -454,6 +454,8 @@ JAVA_JAVA_java = \ sun/misc/JavaLangAccess.java \ sun/misc/JavaIOAccess.java \ sun/misc/JavaIOFileDescriptorAccess.java \ - sun/misc/JavaNioAccess.java + sun/misc/JavaNioAccess.java \ + sun/misc/Perf.java \ + sun/misc/PerfCounter.java FILES_java = $(JAVA_JAVA_java) diff --git a/src/share/classes/java/lang/ClassLoader.java b/src/share/classes/java/lang/ClassLoader.java index dc69abc06..9fec9b570 100644 --- a/src/share/classes/java/lang/ClassLoader.java +++ b/src/share/classes/java/lang/ClassLoader.java @@ -380,6 +380,7 @@ public abstract class ClassLoader { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { + long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); @@ -394,7 +395,13 @@ public abstract class ClassLoader { if (c == null) { // If still not found, then invoke findClass in order // to find the class. + long t1 = System.nanoTime(); c = findClass(name); + + // this is the defining class loader; record the stats + sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); + sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); + sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { diff --git a/src/share/classes/java/net/URLClassLoader.java b/src/share/classes/java/net/URLClassLoader.java index 22be20b7e..c4f775db7 100644 --- a/src/share/classes/java/net/URLClassLoader.java +++ b/src/share/classes/java/net/URLClassLoader.java @@ -340,6 +340,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * used. */ private Class defineClass(String name, Resource res) throws IOException { + long t0 = System.nanoTime(); int i = name.lastIndexOf('.'); URL url = res.getCodeSourceURL(); if (i != -1) { @@ -370,12 +371,14 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { // Use (direct) ByteBuffer: CodeSigner[] signers = res.getCodeSigners(); CodeSource cs = new CodeSource(url, signers); + sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); return defineClass(name, bb, cs); } else { byte[] b = res.getBytes(); // must read certificates AFTER reading bytes. CodeSigner[] signers = res.getCodeSigners(); CodeSource cs = new CodeSource(url, signers); + sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); return defineClass(name, b, 0, b.length, cs); } } diff --git a/src/share/classes/java/util/zip/ZipFile.java b/src/share/classes/java/util/zip/ZipFile.java index 76c270c1b..583d7dcfe 100644 --- a/src/share/classes/java/util/zip/ZipFile.java +++ b/src/share/classes/java/util/zip/ZipFile.java @@ -195,7 +195,10 @@ class ZipFile implements ZipConstants, Closeable { if (charset == null) throw new NullPointerException("charset is null"); this.zc = ZipCoder.get(charset); + long t0 = System.nanoTime(); jzfile = open(name, mode, file.lastModified()); + sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0); + sun.misc.PerfCounter.getZipFileCount().increment(); this.name = name; this.total = getTotal(jzfile); } diff --git a/src/share/classes/sun/misc/PerfCounter.java b/src/share/classes/sun/misc/PerfCounter.java new file mode 100644 index 000000000..8c4723440 --- /dev/null +++ b/src/share/classes/sun/misc/PerfCounter.java @@ -0,0 +1,191 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.misc; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.LongBuffer; +import java.security.AccessController; + +/** + * Performance counter support for internal JRE classes. + * This class defines a fixed list of counters for the platform + * to use as an interim solution until RFE# 6209222 is implemented. + * The perf counters will be created in the jvmstat perf buffer + * that the HotSpot VM creates. The default size is 32K and thus + * the number of counters is bounded. You can alter the size + * with -XX:PerfDataMemorySize= option. If there is + * insufficient memory in the jvmstat perf buffer, the C heap memory + * will be used and thus the application will continue to run if + * the counters added exceeds the buffer size but the counters + * will be missing. + * + * See HotSpot jvmstat implementation for certain circumstances + * that the jvmstat perf buffer is not supported. + * + */ +public class PerfCounter { + private static final Perf perf = + AccessController.doPrivileged(new Perf.GetPerfAction()); + + // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp + private final static int V_Constant = 1; + private final static int V_Monotonic = 2; + private final static int V_Variable = 3; + private final static int U_None = 1; + + private final String name; + private final LongBuffer lb; + + private PerfCounter(String name, int type) { + this.name = name; + ByteBuffer bb = perf.createLong(name, U_None, type, 0L); + bb.order(ByteOrder.nativeOrder()); + this.lb = bb.asLongBuffer(); + } + + static PerfCounter newPerfCounter(String name) { + return new PerfCounter(name, V_Variable); + } + + static PerfCounter newConstantPerfCounter(String name) { + PerfCounter c = new PerfCounter(name, V_Constant); + return c; + } + + /** + * Returns the current value of the perf counter. + */ + public synchronized long get() { + return lb.get(0); + } + + /** + * Sets the value of the perf counter to the given newValue. + */ + public synchronized void set(long newValue) { + lb.put(0, newValue); + } + + /** + * Adds the given value to the perf counter. + */ + public synchronized void add(long value) { + long res = get() + value; + lb.put(0, res); + } + + /** + * Increments the perf counter with 1. + */ + public void increment() { + add(1); + } + + /** + * Adds the given interval to the perf counter. + */ + public void addTime(long interval) { + add(interval); + } + + /** + * Adds the elapsed time from the given start time (ns) to the perf counter. + */ + public void addElapsedTimeFrom(long startTime) { + add(System.nanoTime() - startTime); + } + + @Override + public String toString() { + return name + " = " + get(); + } + + static class CoreCounters { + static final PerfCounter pdt = newPerfCounter("sun.classloader.parentDelegationTime"); + static final PerfCounter lc = newPerfCounter("sun.classloader.findClasses"); + static final PerfCounter lct = newPerfCounter("sun.classloader.findClassTime"); + static final PerfCounter rcbt = newPerfCounter("sun.urlClassLoader.readClassBytesTime"); + static final PerfCounter zfc = newPerfCounter("sun.zip.zipFiles"); + static final PerfCounter zfot = newPerfCounter("sun.zip.zipFile.openTime"); + } + + static class WindowsClientCounters { + static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available"); + } + + /** + * Number of findClass calls + */ + public static PerfCounter getFindClasses() { + return CoreCounters.lc; + } + + /** + * Time (ns) spent in finding classes that includes + * lookup and read class bytes and defineClass + */ + public static PerfCounter getFindClassTime() { + return CoreCounters.lct; + } + + /** + * Time (ns) spent in finding classes + */ + public static PerfCounter getReadClassBytesTime() { + return CoreCounters.rcbt; + } + + /** + * Time (ns) spent in the parent delegation to + * the parent of the defining class loader + */ + public static PerfCounter getParentDelegationTime() { + return CoreCounters.pdt; + } + + /** + * Number of zip files opened. + */ + public static PerfCounter getZipFileCount() { + return CoreCounters.zfc; + } + + /** + * Time (ns) spent in opening the zip files that + * includes building the entries hash table + */ + public static PerfCounter getZipFileOpenTime() { + return CoreCounters.zfot; + } + + /** + * D3D graphic pipeline available + */ + public static PerfCounter getD3DAvailable() { + return WindowsClientCounters.d3dAvailable; + } +} diff --git a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java index a4334b42f..788a4d0ff 100644 --- a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java +++ b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java @@ -67,6 +67,9 @@ public class D3DGraphicsDevice extends Win32GraphicsDevice { if (d3dAvailable) { // we don't use pixel formats for the d3d pipeline pfDisabled = true; + sun.misc.PerfCounter.getD3DAvailable().set(1); + } else { + sun.misc.PerfCounter.getD3DAvailable().set(0); } } -- GitLab