1 /*
   2  * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.misc;
  27 
  28 import java.nio.ByteBuffer;
  29 import java.nio.ByteOrder;
  30 import java.nio.LongBuffer;
  31 import java.security.AccessController;
  32 
  33 /**
  34  * Performance counter support for internal JRE classes.
  35  * This class defines a fixed list of counters for the platform
  36  * to use as an interim solution until RFE# 6209222 is implemented.
  37  * The perf counters will be created in the jvmstat perf buffer
  38  * that the HotSpot VM creates. The default size is 32K and thus
  39  * the number of counters is bounded.  You can alter the size
  40  * with -XX:PerfDataMemorySize=<bytes> option. If there is
  41  * insufficient memory in the jvmstat perf buffer, the C heap memory
  42  * will be used and thus the application will continue to run if
  43  * the counters added exceeds the buffer size but the counters
  44  * will be missing.
  45  *
  46  * See HotSpot jvmstat implementation for certain circumstances
  47  * that the jvmstat perf buffer is not supported.
  48  *
  49  */
  50 public class PerfCounter {
  51     private static final Perf perf =
  52         AccessController.doPrivileged(new Perf.GetPerfAction());
  53 
  54     // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp
  55     private final static int V_Constant  = 1;
  56     private final static int V_Monotonic = 2;
  57     private final static int V_Variable  = 3;
  58     private final static int U_None      = 1;
  59 
  60     private final String name;
  61     private final LongBuffer lb;
  62 
  63     private PerfCounter(String name, int type) {
  64         this.name = name;
  65         ByteBuffer bb = perf.createLong(name, U_None, type, 0L);
  66         bb.order(ByteOrder.nativeOrder());
  67         this.lb = bb.asLongBuffer();
  68     }
  69 
  70     static PerfCounter newPerfCounter(String name) {
  71         return new PerfCounter(name, V_Variable);
  72     }
  73 
  74     static PerfCounter newConstantPerfCounter(String name) {
  75         PerfCounter c = new PerfCounter(name, V_Constant);
  76         return c;
  77     }
  78 
  79     /**
  80      * Returns the current value of the perf counter.
  81      */
  82     public synchronized long get() {
  83         return lb.get(0);
  84     }
  85 
  86     /**
  87      * Sets the value of the perf counter to the given newValue.
  88      */
  89     public synchronized void set(long newValue) {
  90         lb.put(0, newValue);
  91     }
  92 
  93     /**
  94      * Adds the given value to the perf counter.
  95      */
  96     public synchronized void add(long value) {
  97         long res = get() + value;
  98         lb.put(0, res);
  99     }
 100 
 101     /**
 102      * Increments the perf counter with 1.
 103      */
 104     public void increment() {
 105         add(1);
 106     }
 107 
 108     /**
 109      * Adds the given interval to the perf counter.
 110      */
 111     public void addTime(long interval) {
 112         add(interval);
 113     }
 114 
 115     /**
 116      * Adds the elapsed time from the given start time (ns) to the perf counter.
 117      */
 118     public void addElapsedTimeFrom(long startTime) {
 119         add(System.nanoTime() - startTime);
 120     }
 121 
 122     @Override
 123     public String toString() {
 124         return name + " = " + get();
 125     }
 126 
 127     static class CoreCounters {
 128         static final PerfCounter thrownThrowables = newPerfCounter("hotspot.runtime.thrownThrowables");
 129         static final PerfCounter pdt   = newPerfCounter("sun.classloader.parentDelegationTime");
 130         static final PerfCounter lc    = newPerfCounter("sun.classloader.findClasses");
 131         static final PerfCounter lct   = newPerfCounter("sun.classloader.findClassTime");
 132         static final PerfCounter rcbt  = newPerfCounter("sun.urlClassLoader.readClassBytesTime");
 133         static final PerfCounter zfc   = newPerfCounter("sun.zip.zipFiles");
 134         static final PerfCounter zfot  = newPerfCounter("sun.zip.zipFile.openTime");
 135     }
 136 
 137     static class WindowsClientCounters {
 138         static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
 139     }
 140 
 141     /**
 142      * Number of findClass calls
 143      */
 144     public static PerfCounter getFindClasses() {
 145         return CoreCounters.lc;
 146     }
 147 
 148     /**
 149      * Time (ns) spent in finding classes that includes
 150      * lookup and read class bytes and defineClass
 151      */
 152     public static PerfCounter getFindClassTime() {
 153         return CoreCounters.lct;
 154     }
 155 
 156     /**
 157      * Time (ns) spent in finding classes
 158      */
 159     public static PerfCounter getReadClassBytesTime() {
 160         return CoreCounters.rcbt;
 161     }
 162 
 163     /**
 164      * Time (ns) spent in the parent delegation to
 165      * the parent of the defining class loader
 166      */
 167     public static PerfCounter getParentDelegationTime() {
 168         return CoreCounters.pdt;
 169     }
 170 
 171     /**
 172      * Number of zip files opened.
 173      */
 174     public static PerfCounter getZipFileCount() {
 175         return CoreCounters.zfc;
 176     }
 177 
 178     /**
 179      * Time (ns) spent in opening the zip files that
 180      * includes building the entries hash table
 181      */
 182     public static PerfCounter getZipFileOpenTime() {
 183         return CoreCounters.zfot;
 184     }
 185 
 186     /**
 187      * D3D graphic pipeline available
 188      */
 189     public static PerfCounter getD3DAvailable() {
 190         return WindowsClientCounters.d3dAvailable;
 191     }
 192 
 193     /**
 194      * Number of Throwables Thrown
 195      */
 196     public static PerfCounter getThrownThrowables() {
 197         return CoreCounters.thrownThrowables;
 198     }
 199 }