hotspot/src/share/vm/runtime/perfData.cpp
changeset 1 489c9b5090e2
child 5547 f4b087cbb361
equal deleted inserted replaced
0:fd16c54261b3 1:489c9b5090e2
       
     1 /*
       
     2  * Copyright 2001-2005 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  *
       
    23  */
       
    24 
       
    25 # include "incls/_precompiled.incl"
       
    26 # include "incls/_perfData.cpp.incl"
       
    27 
       
    28 PerfDataList*   PerfDataManager::_all = NULL;
       
    29 PerfDataList*   PerfDataManager::_sampled = NULL;
       
    30 PerfDataList*   PerfDataManager::_constants = NULL;
       
    31 
       
    32 /*
       
    33  * The jvmstat global and subsysem jvmstat counter name spaces. The top
       
    34  * level name spaces imply the interface stability level of the counter,
       
    35  * which generally follows the Java package, class, and property naming
       
    36  * conventions. The CounterNS enumeration values should be used to index
       
    37  * into this array.
       
    38  */
       
    39 const char* PerfDataManager::_name_spaces[] = {
       
    40   // top level name spaces
       
    41   "java",                   // stable and supported name space
       
    42   "com.sun",                // unstable but supported name space
       
    43   "sun",                    // unstable and unsupported name space
       
    44   // subsystem name spaces
       
    45   "java.gc",                // Garbage Collection name spaces
       
    46   "com.sun.gc",
       
    47   "sun.gc",
       
    48   "java.ci",                // Compiler name spaces
       
    49   "com.sun.ci",
       
    50   "sun.ci",
       
    51   "java.cls",               // Class Loader name spaces
       
    52   "com.sun.cls",
       
    53   "sun.cls",
       
    54   "java.rt",                // Runtime name spaces
       
    55   "com.sun.rt",
       
    56   "sun.rt",
       
    57   "java.os",                // Operating System name spaces
       
    58   "com.sun.os",
       
    59   "sun.os",
       
    60   "java.threads",           // Threads System name spaces
       
    61   "com.sun.threads",
       
    62   "sun.threads",
       
    63   "java.property",          // Java Property name spaces
       
    64   "com.sun.property",
       
    65   "sun.property",
       
    66   "",
       
    67 };
       
    68 
       
    69 PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v)
       
    70                   : _name(NULL), _u(u), _v(v), _valuep(NULL),
       
    71                     _on_c_heap(false) {
       
    72 
       
    73   const char* prefix = PerfDataManager::ns_to_string(ns);
       
    74 
       
    75   _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2);
       
    76   assert(_name != NULL && strlen(name) != 0, "invalid name");
       
    77 
       
    78   if (ns == NULL_NS) {
       
    79      // No prefix is added to counters with the NULL_NS namespace.
       
    80      strcpy(_name, name);
       
    81      // set the F_Supported flag based on the counter name prefix.
       
    82      if (PerfDataManager::is_stable_supported(_name) ||
       
    83          PerfDataManager::is_unstable_supported(_name)) {
       
    84        _flags = F_Supported;
       
    85      }
       
    86      else {
       
    87        _flags = F_None;
       
    88      }
       
    89   }
       
    90   else {
       
    91     sprintf(_name, "%s.%s", prefix, name);
       
    92     // set the F_Supported flag based on the given namespace.
       
    93     if (PerfDataManager::is_stable_supported(ns) ||
       
    94         PerfDataManager::is_unstable_supported(ns)) {
       
    95       _flags = F_Supported;
       
    96     }
       
    97     else {
       
    98       _flags = F_None;
       
    99     }
       
   100   }
       
   101 }
       
   102 
       
   103 PerfData::~PerfData() {
       
   104   if (_name != NULL) {
       
   105     FREE_C_HEAP_ARRAY(char, _name);
       
   106   }
       
   107   if (is_on_c_heap()) {
       
   108     FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep);
       
   109   }
       
   110 }
       
   111 
       
   112 void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
       
   113 
       
   114   size_t dlen = vlen==0 ? 1 : vlen;
       
   115 
       
   116   size_t namelen = strlen(name()) + 1;  // include null terminator
       
   117   size_t size = sizeof(PerfDataEntry) + namelen;
       
   118   size_t pad_length = ((size % dsize) == 0) ? 0 : dsize - (size % dsize);
       
   119   size += pad_length;
       
   120   size_t data_start = size;
       
   121   size += (dsize * dlen);
       
   122 
       
   123   // align size to assure allocation in units of 8 bytes
       
   124   int align = sizeof(jlong) - 1;
       
   125   size = ((size + align) & ~align);
       
   126   char* psmp = PerfMemory::alloc(size);
       
   127 
       
   128   if (psmp == NULL) {
       
   129     // out of PerfMemory memory resources. allocate on the C heap
       
   130     // to avoid vm termination.
       
   131     psmp = NEW_C_HEAP_ARRAY(char, size);
       
   132     _on_c_heap = true;
       
   133   }
       
   134 
       
   135   // compute the addresses for the name and data
       
   136   char* cname = psmp + sizeof(PerfDataEntry);
       
   137 
       
   138   // data is in the last dsize*dlen bytes of the entry
       
   139   void* valuep = (void*) (psmp + data_start);
       
   140 
       
   141   assert(is_on_c_heap() || PerfMemory::contains(cname), "just checking");
       
   142   assert(is_on_c_heap() || PerfMemory::contains((char*)valuep), "just checking");
       
   143 
       
   144   // copy the name, including null terminator, into PerfData memory
       
   145   strcpy(cname, name());
       
   146 
       
   147 
       
   148   // set the header values in PerfData memory
       
   149   PerfDataEntry* pdep = (PerfDataEntry*)psmp;
       
   150   pdep->entry_length = (jint)size;
       
   151   pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp);
       
   152   pdep->vector_length = (jint)vlen;
       
   153   pdep->data_type = (jbyte) type2char(dtype);
       
   154   pdep->data_units = units();
       
   155   pdep->data_variability = variability();
       
   156   pdep->flags = (jbyte)flags();
       
   157   pdep->data_offset = (jint) data_start;
       
   158 
       
   159   if (PerfTraceDataCreation) {
       
   160     tty->print("name = %s, dtype = %d, variability = %d,"
       
   161                " units = %d, dsize = %d, vlen = %d,"
       
   162                " pad_length = %d, size = %d, on_c_heap = %s,"
       
   163                " address = " INTPTR_FORMAT ","
       
   164                " data address = " INTPTR_FORMAT "\n",
       
   165                cname, dtype, variability(),
       
   166                units(), dsize, vlen,
       
   167                pad_length, size, is_on_c_heap() ? "TRUE":"FALSE",
       
   168                psmp, valuep);
       
   169   }
       
   170 
       
   171   // record the start of the entry and the location of the data field.
       
   172   _pdep = pdep;
       
   173   _valuep = valuep;
       
   174 
       
   175   // mark the PerfData memory region as having been updated.
       
   176   PerfMemory::mark_updated();
       
   177 }
       
   178 
       
   179 PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
       
   180                  : PerfData(ns, namep, u, v) {
       
   181 
       
   182   create_entry(T_LONG, sizeof(jlong));
       
   183 }
       
   184 
       
   185 int PerfLong::format(char* buffer, int length) {
       
   186   return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep);
       
   187 }
       
   188 
       
   189 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
       
   190                                  Variability v, jlong* sampled)
       
   191                                 : PerfLong(ns, namep, u, v),
       
   192                                   _sampled(sampled), _sample_helper(NULL) {
       
   193 
       
   194   sample();
       
   195 }
       
   196 
       
   197 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
       
   198                                  Variability v, PerfLongSampleHelper* helper)
       
   199                                 : PerfLong(ns, namep, u, v),
       
   200                                   _sampled(NULL), _sample_helper(helper) {
       
   201 
       
   202   sample();
       
   203 }
       
   204 
       
   205 void PerfLongVariant::sample() {
       
   206 
       
   207   assert(_sample_helper != NULL || _sampled != NULL, "unexpected state");
       
   208 
       
   209   if (_sample_helper != NULL) {
       
   210     *(jlong*)_valuep = _sample_helper->take_sample();
       
   211   }
       
   212   else if (_sampled != NULL) {
       
   213     *(jlong*)_valuep = *_sampled;
       
   214   }
       
   215 }
       
   216 
       
   217 PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
       
   218                              Variability v, jint length)
       
   219                             : PerfData(ns, namep, u, v), _length(length) {
       
   220 
       
   221   create_entry(T_BYTE, sizeof(jbyte), (size_t)_length);
       
   222 }
       
   223 
       
   224 void PerfString::set_string(const char* s2) {
       
   225 
       
   226   // copy n bytes of the string, assuring the null string is
       
   227   // copied if s2 == NULL.
       
   228   strncpy((char *)_valuep, s2 == NULL ? "" : s2, _length);
       
   229 
       
   230   // assure the string is null terminated when strlen(s2) >= _length
       
   231   ((char*)_valuep)[_length-1] = '\0';
       
   232 }
       
   233 
       
   234 int PerfString::format(char* buffer, int length) {
       
   235   return jio_snprintf(buffer, length, "%s", (char*)_valuep);
       
   236 }
       
   237 
       
   238 PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep,
       
   239                                        const char* initial_value)
       
   240                      : PerfString(ns, namep, V_Constant,
       
   241                                   initial_value == NULL ? 1 :
       
   242                                   MIN2((jint)(strlen((char*)initial_value)+1),
       
   243                                        (jint)(PerfMaxStringConstLength+1)),
       
   244                                   initial_value) {
       
   245 
       
   246   if (PrintMiscellaneous && Verbose) {
       
   247     if (is_valid() && initial_value != NULL &&
       
   248         ((jint)strlen(initial_value) > (jint)PerfMaxStringConstLength)) {
       
   249 
       
   250       warning("Truncating PerfStringConstant: name = %s,"
       
   251               " length = " INT32_FORMAT ","
       
   252               " PerfMaxStringConstLength = " INT32_FORMAT "\n",
       
   253               namep,
       
   254               (jint)strlen(initial_value),
       
   255               (jint)PerfMaxStringConstLength);
       
   256     }
       
   257   }
       
   258 }
       
   259 
       
   260 
       
   261 
       
   262 
       
   263 
       
   264 
       
   265 void PerfDataManager::destroy() {
       
   266 
       
   267   if (_all == NULL)
       
   268     // destroy already called, or initialization never happened
       
   269     return;
       
   270 
       
   271   for (int index = 0; index < _all->length(); index++) {
       
   272     PerfData* p = _all->at(index);
       
   273     delete p;
       
   274   }
       
   275 
       
   276   delete(_all);
       
   277   delete(_sampled);
       
   278   delete(_constants);
       
   279 
       
   280   _all = NULL;
       
   281   _sampled = NULL;
       
   282   _constants = NULL;
       
   283 }
       
   284 
       
   285 void PerfDataManager::add_item(PerfData* p, bool sampled) {
       
   286 
       
   287   MutexLocker ml(PerfDataManager_lock);
       
   288 
       
   289   if (_all == NULL) {
       
   290     _all = new PerfDataList(100);
       
   291   }
       
   292 
       
   293   assert(!_all->contains(p->name()), "duplicate name added");
       
   294 
       
   295   // add to the list of all perf data items
       
   296   _all->append(p);
       
   297 
       
   298   if (p->variability() == PerfData::V_Constant) {
       
   299     if (_constants == NULL) {
       
   300       _constants = new PerfDataList(25);
       
   301     }
       
   302     _constants->append(p);
       
   303     return;
       
   304   }
       
   305 
       
   306   if (sampled) {
       
   307     if (_sampled == NULL) {
       
   308       _sampled = new PerfDataList(25);
       
   309     }
       
   310     _sampled->append(p);
       
   311   }
       
   312 }
       
   313 
       
   314 PerfDataList* PerfDataManager::all() {
       
   315 
       
   316   MutexLocker ml(PerfDataManager_lock);
       
   317 
       
   318   if (_all == NULL)
       
   319     return NULL;
       
   320 
       
   321   PerfDataList* clone = _all->clone();
       
   322   return clone;
       
   323 }
       
   324 
       
   325 PerfDataList* PerfDataManager::sampled() {
       
   326 
       
   327   MutexLocker ml(PerfDataManager_lock);
       
   328 
       
   329   if (_sampled == NULL)
       
   330     return NULL;
       
   331 
       
   332   PerfDataList* clone = _sampled->clone();
       
   333   return clone;
       
   334 }
       
   335 
       
   336 PerfDataList* PerfDataManager::constants() {
       
   337 
       
   338   MutexLocker ml(PerfDataManager_lock);
       
   339 
       
   340   if (_constants == NULL)
       
   341     return NULL;
       
   342 
       
   343   PerfDataList* clone = _constants->clone();
       
   344   return clone;
       
   345 }
       
   346 
       
   347 char* PerfDataManager::counter_name(const char* ns, const char* name) {
       
   348    assert(ns != NULL, "ns string required");
       
   349    assert(name != NULL, "name string required");
       
   350 
       
   351    size_t len = strlen(ns) + strlen(name) + 2;
       
   352    char* result = NEW_RESOURCE_ARRAY(char, len);
       
   353    sprintf(result, "%s.%s", ns, name);
       
   354    return result;
       
   355 }
       
   356 
       
   357 char* PerfDataManager::name_space(const char* ns, const char* sub,
       
   358                                   int instance) {
       
   359    char intbuf[40];
       
   360    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
       
   361    return name_space(ns, name_space(sub, intbuf));
       
   362 }
       
   363 
       
   364 char *PerfDataManager::name_space(const char* ns, int instance) {
       
   365    char intbuf[40];
       
   366    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
       
   367    return name_space(ns, intbuf);
       
   368 }
       
   369 
       
   370 PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns,
       
   371                                                             const char* name,
       
   372                                                             const char* s,
       
   373                                                             TRAPS) {
       
   374 
       
   375   PerfStringConstant* p = new PerfStringConstant(ns, name, s);
       
   376 
       
   377   if (!p->is_valid()) {
       
   378     // allocation of native resources failed.
       
   379     delete p;
       
   380     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   381   }
       
   382 
       
   383   add_item(p, false);
       
   384 
       
   385   return p;
       
   386 }
       
   387 
       
   388 PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns,
       
   389                                                         const char* name,
       
   390                                                         PerfData::Units u,
       
   391                                                         jlong val, TRAPS) {
       
   392 
       
   393   PerfLongConstant* p = new PerfLongConstant(ns, name, u, val);
       
   394 
       
   395   if (!p->is_valid()) {
       
   396     // allocation of native resources failed.
       
   397     delete p;
       
   398     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   399   }
       
   400 
       
   401   add_item(p, false);
       
   402 
       
   403   return p;
       
   404 }
       
   405 
       
   406 PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
       
   407                                                             const char* name,
       
   408                                                             jint max_length,
       
   409                                                             const char* s,
       
   410                                                             TRAPS) {
       
   411 
       
   412   if (max_length == 0 && s != NULL) max_length = (jint)strlen(s);
       
   413 
       
   414   assert(max_length != 0, "PerfStringVariable with length 0");
       
   415 
       
   416   PerfStringVariable* p = new PerfStringVariable(ns, name, max_length, s);
       
   417 
       
   418   if (!p->is_valid()) {
       
   419     // allocation of native resources failed.
       
   420     delete p;
       
   421     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   422   }
       
   423 
       
   424   add_item(p, false);
       
   425 
       
   426   return p;
       
   427 }
       
   428 
       
   429 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
       
   430                                                         const char* name,
       
   431                                                         PerfData::Units u,
       
   432                                                         jlong ival, TRAPS) {
       
   433 
       
   434   PerfLongVariable* p = new PerfLongVariable(ns, name, u, ival);
       
   435 
       
   436   if (!p->is_valid()) {
       
   437     // allocation of native resources failed.
       
   438     delete p;
       
   439     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   440   }
       
   441 
       
   442   add_item(p, false);
       
   443 
       
   444   return p;
       
   445 }
       
   446 
       
   447 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
       
   448                                                         const char* name,
       
   449                                                         PerfData::Units u,
       
   450                                                         jlong* sp, TRAPS) {
       
   451 
       
   452   // Sampled counters not supported if UsePerfData is false
       
   453   if (!UsePerfData) return NULL;
       
   454 
       
   455   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp);
       
   456 
       
   457   if (!p->is_valid()) {
       
   458     // allocation of native resources failed.
       
   459     delete p;
       
   460     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   461   }
       
   462 
       
   463   add_item(p, true);
       
   464 
       
   465   return p;
       
   466 }
       
   467 
       
   468 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
       
   469                                                         const char* name,
       
   470                                                         PerfData::Units u,
       
   471                                                         PerfSampleHelper* sh,
       
   472                                                         TRAPS) {
       
   473 
       
   474   // Sampled counters not supported if UsePerfData is false
       
   475   if (!UsePerfData) return NULL;
       
   476 
       
   477   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh);
       
   478 
       
   479   if (!p->is_valid()) {
       
   480     // allocation of native resources failed.
       
   481     delete p;
       
   482     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   483   }
       
   484 
       
   485   add_item(p, true);
       
   486 
       
   487   return p;
       
   488 }
       
   489 
       
   490 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
       
   491                                                       const char* name,
       
   492                                                       PerfData::Units u,
       
   493                                                       jlong ival, TRAPS) {
       
   494 
       
   495   PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival);
       
   496 
       
   497   if (!p->is_valid()) {
       
   498     // allocation of native resources failed.
       
   499     delete p;
       
   500     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   501   }
       
   502 
       
   503   add_item(p, false);
       
   504 
       
   505   return p;
       
   506 }
       
   507 
       
   508 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
       
   509                                                       const char* name,
       
   510                                                       PerfData::Units u,
       
   511                                                       jlong* sp, TRAPS) {
       
   512 
       
   513   // Sampled counters not supported if UsePerfData is false
       
   514   if (!UsePerfData) return NULL;
       
   515 
       
   516   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp);
       
   517 
       
   518   if (!p->is_valid()) {
       
   519     // allocation of native resources failed.
       
   520     delete p;
       
   521     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   522   }
       
   523 
       
   524   add_item(p, true);
       
   525 
       
   526   return p;
       
   527 }
       
   528 
       
   529 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
       
   530                                                       const char* name,
       
   531                                                       PerfData::Units u,
       
   532                                                       PerfSampleHelper* sh,
       
   533                                                       TRAPS) {
       
   534 
       
   535   // Sampled counters not supported if UsePerfData is false
       
   536   if (!UsePerfData) return NULL;
       
   537 
       
   538   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh);
       
   539 
       
   540   if (!p->is_valid()) {
       
   541     // allocation of native resources failed.
       
   542     delete p;
       
   543     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
       
   544   }
       
   545 
       
   546   add_item(p, true);
       
   547 
       
   548   return p;
       
   549 }
       
   550 
       
   551 PerfDataList::PerfDataList(int length) {
       
   552 
       
   553   _set = new(ResourceObj::C_HEAP) PerfDataArray(length, true);
       
   554 }
       
   555 
       
   556 PerfDataList::PerfDataList(PerfDataList* p) {
       
   557 
       
   558   _set = new(ResourceObj::C_HEAP) PerfDataArray(p->length(), true);
       
   559 
       
   560   _set->appendAll(p->get_impl());
       
   561 }
       
   562 
       
   563 PerfDataList::~PerfDataList() {
       
   564 
       
   565   delete _set;
       
   566 
       
   567 }
       
   568 
       
   569 bool PerfDataList::by_name(void* name, PerfData* pd) {
       
   570 
       
   571   if (pd == NULL)
       
   572     return false;
       
   573 
       
   574   return strcmp((const char*)name, pd->name()) == 0;
       
   575 }
       
   576 
       
   577 PerfData* PerfDataList::find_by_name(const char* name) {
       
   578 
       
   579   int i = _set->find((void*)name, PerfDataList::by_name);
       
   580 
       
   581   if (i >= 0 && i <= _set->length())
       
   582     return _set->at(i);
       
   583   else
       
   584     return NULL;
       
   585 }
       
   586 
       
   587 PerfDataList* PerfDataList::clone() {
       
   588 
       
   589   PerfDataList* copy = new PerfDataList(this);
       
   590 
       
   591   assert(copy != NULL, "just checking");
       
   592 
       
   593   return copy;
       
   594 }