jdk/src/share/classes/sun/misc/Perf.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2002-2006 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 package sun.misc;
       
    26 
       
    27 import java.nio.ByteBuffer;
       
    28 import java.security.Permission;
       
    29 import java.security.PrivilegedAction;
       
    30 import java.io.IOException;
       
    31 import java.io.UnsupportedEncodingException;
       
    32 
       
    33 /**
       
    34  * The Perf class provides the ability to attach to an instrumentation
       
    35  * buffer maintained by a Java virtual machine. The instrumentation
       
    36  * buffer may be for the Java virtual machine running the methods of
       
    37  * this class or it may be for another Java virtual machine on the
       
    38  * same system.
       
    39  * <p>
       
    40  * In addition, this class provides methods to create instrumentation
       
    41  * objects in the instrumentation buffer for the Java virtual machine
       
    42  * that is running these methods. It also contains methods for acquiring
       
    43  * the value of a platform specific high resolution clock for time
       
    44  * stamp and interval measurement purposes.
       
    45  *
       
    46  * @author   Brian Doherty
       
    47  * @since    1.4.2
       
    48  * @see      #getPerf
       
    49  * @see      sun.misc.Perf$GetPerfAction
       
    50  * @see      java.nio.ByteBuffer
       
    51  */
       
    52 public final class Perf {
       
    53 
       
    54     private static Perf instance;
       
    55 
       
    56     private static final int PERF_MODE_RO = 0;
       
    57     private static final int PERF_MODE_RW = 1;
       
    58 
       
    59     private Perf() { }    // prevent instantiation
       
    60 
       
    61     /**
       
    62      * The GetPerfAction class is a convenience class for acquiring access
       
    63      * to the singleton Perf instance using the
       
    64      * <code>AccessController.doPrivileged()</code> method.
       
    65      * <p>
       
    66      * An instance of this class can be used as the argument to
       
    67      * <code>AccessController.doPrivileged(PrivilegedAction)</code>.
       
    68      * <p> Here is a suggested idiom for use of this class:
       
    69      *
       
    70      * <blockquote><pre>
       
    71      * class MyTrustedClass {
       
    72      *   private static final Perf perf =
       
    73      *       AccessController.doPrivileged(new Perf.GetPerfAction<Perf>());
       
    74      *   ...
       
    75      * }
       
    76      * </pre></blockquote>
       
    77      * <p>
       
    78      * In the presence of a security manager, the <code>MyTrustedClass</code>
       
    79      * class in the above example will need to be granted the
       
    80      * <em>"sun.misc.Perf.getPerf"</em> <code>RuntimePermission</code>
       
    81      * permission in order to successfully acquire the singleton Perf instance.
       
    82      * <p>
       
    83      * Please note that the <em>"sun.misc.Perf.getPerf"</em> permission
       
    84      * is not a JDK specified permission.
       
    85      *
       
    86      * @see  java.security.AccessController#doPrivileged(PrivilegedAction)
       
    87      * @see  java.lang.RuntimePermission
       
    88      */
       
    89     public static class GetPerfAction implements PrivilegedAction<Perf>
       
    90     {
       
    91         /**
       
    92          * Run the <code>Perf.getPerf()</code> method in a privileged context.
       
    93          *
       
    94          * @see #getPerf
       
    95          */
       
    96         public Perf run() {
       
    97             return getPerf();
       
    98         }
       
    99     }
       
   100 
       
   101     /**
       
   102      * Return a reference to the singleton Perf instance.
       
   103      * <p>
       
   104      * The getPerf() method returns the singleton instance of the Perf
       
   105      * class. The returned object provides the caller with the capability
       
   106      * for accessing the instrumentation buffer for this or another local
       
   107      * Java virtual machine.
       
   108      * <p>
       
   109      * If a security manager is installed, its <code>checkPermission</code>
       
   110      * method is called with a <code>RuntimePermission</code> with a target
       
   111      * of <em>"sun.misc.Perf.getPerf"</em>. A security exception will result
       
   112      * if the caller has not been granted this permission.
       
   113      * <p>
       
   114      * Access to the returned <code>Perf</code> object should be protected
       
   115      * by its caller and not passed on to untrusted code. This object can
       
   116      * be used to attach to the instrumentation buffer provided by this Java
       
   117      * virtual machine or for those of other Java virtual machines running
       
   118      * on the same system. The instrumentation buffer may contain senstitive
       
   119      * information. API's built on top of this interface may want to provide
       
   120      * finer grained access control to the contents of individual
       
   121      * instrumentation objects contained within the buffer.
       
   122      * <p>
       
   123      * Please note that the <em>"sun.misc.Perf.getPerf"</em> permission
       
   124      * is not a JDK specified permission.
       
   125      *
       
   126      * @return       A reference to the singleton Perf instance.
       
   127      * @throws AccessControlException  if a security manager exists and
       
   128      *               its <code>checkPermission</code> method doesn't allow
       
   129      *               access to the <em>"sun.misc.Perf.getPerf"</em> target.
       
   130      * @see  java.lang.RuntimePermission
       
   131      * @see  #attach
       
   132      */
       
   133     public static Perf getPerf()
       
   134     {
       
   135         SecurityManager security = System.getSecurityManager();
       
   136         if (security != null) {
       
   137             Permission perm = new RuntimePermission("sun.misc.Perf.getPerf");
       
   138             security.checkPermission(perm);
       
   139         }
       
   140 
       
   141         return instance;
       
   142     }
       
   143 
       
   144     /**
       
   145      * Attach to the instrumentation buffer for the specified Java virtual
       
   146      * machine.
       
   147      * <p>
       
   148      * This method will attach to the instrumentation buffer for the
       
   149      * specified virtual machine. It returns a <code>ByteBuffer</code> object
       
   150      * that is initialized to access the instrumentation buffer for the
       
   151      * indicated Java virtual machine. The <code>lvmid</code> parameter is
       
   152      * a integer value that uniquely identifies the target local Java virtual
       
   153      * machine. It is typically, but not necessarily, the process id of
       
   154      * the target Java virtual machine.
       
   155      * <p>
       
   156      * If the <code>lvmid</code> identifies a Java virtual machine different
       
   157      * from the one running this method, then the coherency characteristics
       
   158      * of the buffer are implementation dependent. Implementations that do
       
   159      * not support named, coherent, shared memory may return a
       
   160      * <code>ByteBuffer</code> object that contains only a snap shot of the
       
   161      * data in the instrumentation buffer. Implementations that support named,
       
   162      * coherent, shared memory, may return a <code>ByteBuffer</code> object
       
   163      * that will be changing dynamically over time as the target Java virtual
       
   164      * machine updates its mapping of this buffer.
       
   165      * <p>
       
   166      * If the <code>lvmid</code> is 0 or equal to the actual <code>lvmid</code>
       
   167      * for the Java virtual machine running this method, then the returned
       
   168      * <code>ByteBuffer</code> object will always be coherent and dynamically
       
   169      * changing.
       
   170      * <p>
       
   171      * The attach mode specifies the access permissions requested for the
       
   172      * instrumentation buffer of the target virtual machine. The permitted
       
   173      * access permissions are:
       
   174      * <p>
       
   175      * <bl>
       
   176      * <li>"r"  - Read only access. This Java virtual machine has only
       
   177      * read access to the instrumentation buffer for the target Java
       
   178      * virtual machine.
       
   179      * <li>"rw"  - Read/Write access. This Java virtual machine has read and
       
   180      * write access to the instrumentation buffer for the target Java virtual
       
   181      * machine. This mode is currently not supported and is reserved for
       
   182      * future enhancements.
       
   183      * </bl>
       
   184      *
       
   185      * @param   lvmid            an integer that uniquely identifies the
       
   186      *                           target local Java virtual machine.
       
   187      * @param   mode             a string indicating the attach mode.
       
   188      * @return  ByteBuffer       a direct allocated byte buffer
       
   189      * @throws  IllegalArgumentException  The lvmid or mode was invalid.
       
   190      * @throws  IOException      An I/O error occurred while trying to acquire
       
   191      *                           the instrumentation buffer.
       
   192      * @throws  OutOfMemoryError The instrumentation buffer could not be mapped
       
   193      *                           into the virtual machine's address space.
       
   194      * @see     java.nio.ByteBuffer
       
   195      */
       
   196     public ByteBuffer attach(int lvmid, String mode)
       
   197            throws IllegalArgumentException, IOException
       
   198     {
       
   199         if (mode.compareTo("r") == 0) {
       
   200             return attachImpl(null, lvmid, PERF_MODE_RO);
       
   201         }
       
   202         else if (mode.compareTo("rw") == 0) {
       
   203             return attachImpl(null, lvmid, PERF_MODE_RW);
       
   204         }
       
   205         else {
       
   206             throw new IllegalArgumentException("unknown mode");
       
   207         }
       
   208     }
       
   209 
       
   210     /**
       
   211      * Attach to the instrumentation buffer for the specified Java virtual
       
   212      * machine owned by the given user.
       
   213      * <p>
       
   214      * This method behaves just as the <code>attach(int lvmid, String mode)
       
   215      * </code> method, except that it only searches for Java virtual machines
       
   216      * owned by the specified user.
       
   217      *
       
   218      * @param   user             A <code>String</code> object containing the
       
   219      *                           name of the user that owns the target Java
       
   220      *                           virtual machine.
       
   221      * @param   lvmid            an integer that uniquely identifies the
       
   222      *                           target local Java virtual machine.
       
   223      * @param   mode             a string indicating the attach mode.
       
   224      * @return  ByteBuffer       a direct allocated byte buffer
       
   225      * @throws  IllegalArgumentException  The lvmid or mode was invalid.
       
   226      * @throws  IOException      An I/O error occurred while trying to acquire
       
   227      *                           the instrumentation buffer.
       
   228      * @throws  OutOfMemoryError The instrumentation buffer could not be mapped
       
   229      *                           into the virtual machine's address space.
       
   230      * @see     java.nio.ByteBuffer
       
   231      */
       
   232     public ByteBuffer attach(String user, int lvmid, String mode)
       
   233            throws IllegalArgumentException, IOException
       
   234     {
       
   235         if (mode.compareTo("r") == 0) {
       
   236             return attachImpl(user, lvmid, PERF_MODE_RO);
       
   237         }
       
   238         else if (mode.compareTo("rw") == 0) {
       
   239             return attachImpl(user, lvmid, PERF_MODE_RW);
       
   240         }
       
   241         else {
       
   242             throw new IllegalArgumentException("unknown mode");
       
   243         }
       
   244     }
       
   245 
       
   246     /**
       
   247      * Call the implementation specific attach method.
       
   248      * <p>
       
   249      * This method calls into the Java virtual machine to perform the platform
       
   250      * specific attach method. Buffers returned from this method are
       
   251      * internally managed as <code>PhantomRefereces</code> to provide for
       
   252      * guaranteed, secure release of the native resources.
       
   253      *
       
   254      * @param   user             A <code>String</code> object containing the
       
   255      *                           name of the user that owns the target Java
       
   256      *                           virtual machine.
       
   257      * @param   lvmid            an integer that uniquely identifies the
       
   258      *                           target local Java virtual machine.
       
   259      * @param   mode             a string indicating the attach mode.
       
   260      * @return  ByteBuffer       a direct allocated byte buffer
       
   261      * @throws  IllegalArgumentException  The lvmid or mode was invalid.
       
   262      * @throws  IOException      An I/O error occurred while trying to acquire
       
   263      *                           the instrumentation buffer.
       
   264      * @throws  OutOfMemoryError The instrumentation buffer could not be mapped
       
   265      *                           into the virtual machine's address space.
       
   266      */
       
   267     private ByteBuffer attachImpl(String user, int lvmid, int mode)
       
   268             throws IllegalArgumentException, IOException
       
   269     {
       
   270         final ByteBuffer b = attach(user, lvmid, mode);
       
   271 
       
   272         if (lvmid == 0) {
       
   273             // The native instrumentation buffer for this Java virtual
       
   274             // machine is never unmapped.
       
   275             return b;
       
   276         }
       
   277         else {
       
   278             // This is an instrumentation buffer for another Java virtual
       
   279             // machine with native resources that need to be managed. We
       
   280             // create a duplicate of the native ByteBuffer and manage it
       
   281             // with a Cleaner object (PhantomReference). When the duplicate
       
   282             // becomes only phantomly reachable, the native resources will
       
   283             // be released.
       
   284 
       
   285             final ByteBuffer dup = b.duplicate();
       
   286             Cleaner.create(dup, new Runnable() {
       
   287                     public void run() {
       
   288                         try {
       
   289                             instance.detach(b);
       
   290                         }
       
   291                         catch (Throwable th) {
       
   292                             // avoid crashing the reference handler thread,
       
   293                             // but provide for some diagnosability
       
   294                             assert false : th.toString();
       
   295                         }
       
   296                     }
       
   297                 });
       
   298             return dup;
       
   299         }
       
   300     }
       
   301 
       
   302     /**
       
   303      * Native method to perform the implementation specific attach mechanism.
       
   304      * <p>
       
   305      * The implementation of this method may return distinct or identical
       
   306      * <code>ByteBuffer</code> objects for two distinct calls requesting
       
   307      * attachment to the same Java virtual machine.
       
   308      * <p>
       
   309      * For the Sun HotSpot JVM, two distinct calls to attach to the same
       
   310      * target Java virtual machine will result in two distinct ByteBuffer
       
   311      * objects returned by this method. This may change in a future release.
       
   312      *
       
   313      * @param   user             A <code>String</code> object containing the
       
   314      *                           name of the user that owns the target Java
       
   315      *                           virtual machine.
       
   316      * @param   lvmid            an integer that uniquely identifies the
       
   317      *                           target local Java virtual machine.
       
   318      * @param   mode             a string indicating the attach mode.
       
   319      * @return  ByteBuffer       a direct allocated byte buffer
       
   320      * @throws  IllegalArgumentException  The lvmid or mode was invalid.
       
   321      * @throws  IOException      An I/O error occurred while trying to acquire
       
   322      *                           the instrumentation buffer.
       
   323      * @throws  OutOfMemoryError The instrumentation buffer could not be mapped
       
   324      *                           into the virtual machine's address space.
       
   325      */
       
   326     private native ByteBuffer attach(String user, int lvmid, int mode)
       
   327                    throws IllegalArgumentException, IOException;
       
   328 
       
   329     /**
       
   330      * Native method to perform the implementation specific detach mechanism.
       
   331      * <p>
       
   332      * If this method is passed a <code>ByteBuffer</code> object that is
       
   333      * not created by the <code>attach</code> method, then the results of
       
   334      * this method are undefined, with unpredictable and potentially damaging
       
   335      * effects to the Java virtual machine. To prevent accidental or malicious
       
   336      * use of this method, all native ByteBuffer created by the <code>
       
   337      * attach</code> method are managed internally as PhantomReferences
       
   338      * and resources are freed by the system.
       
   339      * <p>
       
   340      * If this method is passed a <code>ByteBuffer</code> object created
       
   341      * by the <code>attach</code> method with a lvmid for the Java virtual
       
   342      * machine running this method (lvmid=0, for example), then the detach
       
   343      * request is silently ignored.
       
   344      *
       
   345      * @param ByteBuffer  A direct allocated byte buffer created by the
       
   346      *                    <code>attach</code> method.
       
   347      * @see   java.nio.ByteBuffer
       
   348      * @see   #attach
       
   349      */
       
   350     private native void detach(ByteBuffer bb);
       
   351 
       
   352     /**
       
   353      * Create a <code>long</code> scalar entry in the instrumentation buffer
       
   354      * with the given variability characteristic, units, and initial value.
       
   355      * <p>
       
   356      * Access to the instrument is provided through the returned <code>
       
   357      * ByteBuffer</code> object. Typically, this object should be wrapped
       
   358      * with <code>LongBuffer</code> view object.
       
   359      *
       
   360      * @param   variability the variability characteristic for this entry.
       
   361      * @param   units       the units for this entry.
       
   362      * @param   name        the name of this entry.
       
   363      * @param   value       the initial value for this entry.
       
   364      * @return  ByteBuffer  a direct allocated ByteBuffer object that
       
   365      *                      allows write access to a native memory location
       
   366      *                      containing a <code>long</code> value.
       
   367      *
       
   368      * see sun.misc.perf.Variability
       
   369      * see sun.misc.perf.Units
       
   370      * @see java.nio.ByteBuffer
       
   371      */
       
   372     public native ByteBuffer createLong(String name, int variability,
       
   373                                         int units, long value);
       
   374 
       
   375     /**
       
   376      * Create a <code>String</code> entry in the instrumentation buffer with
       
   377      * the given variability characteristic, units, and initial value.
       
   378      * <p>
       
   379      * The maximum length of the <code>String</code> stored in this string
       
   380      * instrument is given in by <code>maxLength</code> parameter. Updates
       
   381      * to this instrument with <code>String</code> values with lengths greater
       
   382      * than <code>maxLength</code> will be truncated to <code>maxLength</code>.
       
   383      * The truncated value will be terminated by a null character.
       
   384      * <p>
       
   385      * The underlying implementation may further limit the length of the
       
   386      * value, but will continue to preserve the null terminator.
       
   387      * <p>
       
   388      * Access to the instrument is provided through the returned <code>
       
   389      * ByteBuffer</code> object.
       
   390      *
       
   391      * @param   variability the variability characteristic for this entry.
       
   392      * @param   units       the units for this entry.
       
   393      * @param   name        the name of this entry.
       
   394      * @param   value       the initial value for this entry.
       
   395      * @param   maxLength   the maximum string length for this string
       
   396      *                      instrument.
       
   397      * @return  ByteBuffer  a direct allocated ByteBuffer that allows
       
   398      *                      write access to a native memory location
       
   399      *                      containing a <code>long</code> value.
       
   400      *
       
   401      * see sun.misc.perf.Variability
       
   402      * see sun.misc.perf.Units
       
   403      * @see java.nio.ByteBuffer
       
   404      */
       
   405     public ByteBuffer createString(String name, int variability,
       
   406                                    int units, String value, int maxLength)
       
   407     {
       
   408         byte[] v = getBytes(value);
       
   409         byte[] v1 = new byte[v.length+1];
       
   410         System.arraycopy(v, 0, v1, 0, v.length);
       
   411         v1[v.length] = '\0';
       
   412         return createByteArray(name, variability, units, v1, Math.max(v1.length, maxLength));
       
   413     }
       
   414 
       
   415     /**
       
   416      * Create a <code>String</code> entry in the instrumentation buffer with
       
   417      * the given variability characteristic, units, and initial value.
       
   418      * <p>
       
   419      * The maximum length of the <code>String</code> stored in this string
       
   420      * instrument is implied by the length of the <code>value</code> parameter.
       
   421      * Subsequent updates to the value of this instrument will be truncated
       
   422      * to this implied maximum length. The truncated value will be terminated
       
   423      * by a null character.
       
   424      * <p>
       
   425      * The underlying implementation may further limit the length of the
       
   426      * initial or subsequent value, but will continue to preserve the null
       
   427      * terminator.
       
   428      * <p>
       
   429      * Access to the instrument is provided through the returned <code>
       
   430      * ByteBuffer</code> object.
       
   431      *
       
   432      * @param   variability the variability characteristic for this entry.
       
   433      * @param   units       the units for this entry.
       
   434      * @param   name        the name of this entry.
       
   435      * @param   value       the initial value for this entry.
       
   436      * @return  ByteBuffer  a direct allocated ByteBuffer that allows
       
   437      *                      write access to a native memory location
       
   438      *                      containing a <code>long</code> value.
       
   439      *
       
   440      * see sun.misc.perf.Variability
       
   441      * see sun.misc.perf.Units
       
   442      * @see java.nio.ByteBuffer
       
   443      */
       
   444     public ByteBuffer createString(String name, int variability,
       
   445                                    int units, String value)
       
   446     {
       
   447         byte[] v = getBytes(value);
       
   448         byte[] v1 = new byte[v.length+1];
       
   449         System.arraycopy(v, 0, v1, 0, v.length);
       
   450         v1[v.length] = '\0';
       
   451         return createByteArray(name, variability, units, v1, v1.length);
       
   452     }
       
   453 
       
   454     /**
       
   455      * Create a <code>byte</code> vector entry in the instrumentation buffer
       
   456      * with the given variability characteristic, units, and initial value.
       
   457      * <p>
       
   458      * The <code>maxLength</code> parameter limits the size of the byte
       
   459      * array instrument such that the initial or subsequent updates beyond
       
   460      * this length are silently ignored. No special handling of truncated
       
   461      * updates is provided.
       
   462      * <p>
       
   463      * The underlying implementation may further limit the length of the
       
   464      * length of the initial or subsequent value.
       
   465      * <p>
       
   466      * Access to the instrument is provided through the returned <code>
       
   467      * ByteBuffer</code> object.
       
   468      *
       
   469      * @param   variability the variability characteristic for this entry.
       
   470      * @param   units       the units for this entry.
       
   471      * @param   name        the name of this entry.
       
   472      * @param   value       the initial value for this entry.
       
   473      * @param   maxLength   the maximum length of this byte array.
       
   474      * @return  ByteBuffer  a direct allocated byte buffer that allows
       
   475      *                      write access to a native memory location
       
   476      *                      containing a <code>long</code> value.
       
   477      *
       
   478      * see sun.misc.perf.Variability
       
   479      * see sun.misc.perf.Units
       
   480      * @see java.nio.ByteBuffer
       
   481      */
       
   482     public native ByteBuffer createByteArray(String name, int variability,
       
   483                                              int units, byte[] value,
       
   484                                              int maxLength);
       
   485 
       
   486 
       
   487     /**
       
   488      * convert string to an array of UTF-8 bytes
       
   489      */
       
   490     private static byte[] getBytes(String s)
       
   491     {
       
   492         byte[] bytes = null;
       
   493 
       
   494         try {
       
   495             bytes = s.getBytes("UTF-8");
       
   496         }
       
   497         catch (UnsupportedEncodingException e) {
       
   498             // ignore, UTF-8 encoding is always known
       
   499         }
       
   500 
       
   501         return bytes;
       
   502     }
       
   503 
       
   504     /**
       
   505      * Return the value of the High Resolution Counter.
       
   506      *
       
   507      * The High Resolution Counter returns the number of ticks since
       
   508      * since the start of the Java virtual machine. The resolution of
       
   509      * the counter is machine dependent and can be determined from the
       
   510      * value return by the {@link #highResFrequency} method.
       
   511      *
       
   512      * @return  the number of ticks of machine dependent resolution since
       
   513      *          the start of the Java virtual machine.
       
   514      *
       
   515      * @see #highResFrequency
       
   516      * @see java.lang.System#currentTimeMillis()
       
   517      */
       
   518     public native long highResCounter();
       
   519 
       
   520     /**
       
   521      * Returns the frequency of the High Resolution Counter, in ticks per
       
   522      * second.
       
   523      *
       
   524      * This value can be used to convert the value of the High Resolution
       
   525      * Counter, as returned from a call to the {@link #highResCounter} method,
       
   526      * into the number of seconds since the start of the Java virtual machine.
       
   527      *
       
   528      * @return  the frequency of the High Resolution Counter.
       
   529      * @see #highResCounter
       
   530      */
       
   531     public native long highResFrequency();
       
   532 
       
   533     private static native void registerNatives();
       
   534 
       
   535     static {
       
   536         registerNatives();
       
   537         instance = new Perf();
       
   538     }
       
   539 }