hotspot/src/share/vm/runtime/statSampler.cpp
changeset 1 489c9b5090e2
child 987 843415f667e6
equal deleted inserted replaced
0:fd16c54261b3 1:489c9b5090e2
       
     1 /*
       
     2  * Copyright 2001-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.
       
     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/_statSampler.cpp.incl"
       
    27 
       
    28 // --------------------------------------------------------
       
    29 // StatSamplerTask
       
    30 
       
    31 class StatSamplerTask : public PeriodicTask {
       
    32   public:
       
    33     StatSamplerTask(int interval_time) : PeriodicTask(interval_time) {}
       
    34     void task() { StatSampler::collect_sample(); }
       
    35 };
       
    36 
       
    37 
       
    38 //----------------------------------------------------------
       
    39 // Implementation of StatSampler
       
    40 
       
    41 StatSamplerTask*              StatSampler::_task   = NULL;
       
    42 PerfDataList*                 StatSampler::_sampled = NULL;
       
    43 
       
    44 /*
       
    45  * the initialize method is called from the engage() method
       
    46  * and is responsible for initializing various global variables.
       
    47  */
       
    48 void StatSampler::initialize() {
       
    49 
       
    50   if (!UsePerfData) return;
       
    51 
       
    52   // create performance data that could not be created prior
       
    53   // to vm_init_globals() or otherwise have no logical home.
       
    54 
       
    55   create_misc_perfdata();
       
    56 
       
    57   // get copy of the sampled list
       
    58   _sampled = PerfDataManager::sampled();
       
    59 
       
    60 }
       
    61 
       
    62 /*
       
    63  * The engage() method is called at initialization time via
       
    64  * Thread::create_vm() to initialize the StatSampler and
       
    65  * register it with the WatcherThread as a periodic task.
       
    66  */
       
    67 void StatSampler::engage() {
       
    68 
       
    69   if (!UsePerfData) return;
       
    70 
       
    71   if (!is_active()) {
       
    72 
       
    73     initialize();
       
    74 
       
    75     // start up the periodic task
       
    76     _task = new StatSamplerTask(PerfDataSamplingInterval);
       
    77     _task->enroll();
       
    78   }
       
    79 }
       
    80 
       
    81 
       
    82 /*
       
    83  * the disengage() method is responsible for deactivating the periodic
       
    84  * task and, if logging was enabled, for logging the final sample. This
       
    85  * method is called from before_exit() in java.cpp and is only called
       
    86  * after the WatcherThread has been stopped.
       
    87  */
       
    88 void StatSampler::disengage() {
       
    89 
       
    90   if (!UsePerfData) return;
       
    91 
       
    92   if (!is_active())
       
    93     return;
       
    94 
       
    95   // remove StatSamplerTask
       
    96   _task->disenroll();
       
    97   delete _task;
       
    98   _task = NULL;
       
    99 
       
   100   // force a final sample
       
   101   sample_data(_sampled);
       
   102 }
       
   103 
       
   104 /*
       
   105  * the destroy method is responsible for releasing any resources used by
       
   106  * the StatSampler prior to shutdown of the VM. this method is called from
       
   107  * before_exit() in java.cpp and is only called after the WatcherThread
       
   108  * has stopped.
       
   109  */
       
   110 void StatSampler::destroy() {
       
   111 
       
   112   if (!UsePerfData) return;
       
   113 
       
   114   if (_sampled != NULL) {
       
   115     delete(_sampled);
       
   116     _sampled = NULL;
       
   117   }
       
   118 }
       
   119 
       
   120 /*
       
   121  * The sample_data() method is responsible for sampling the
       
   122  * the data value for each PerfData instance in the given list.
       
   123  */
       
   124 void StatSampler::sample_data(PerfDataList* list) {
       
   125 
       
   126   assert(list != NULL, "null list unexpected");
       
   127 
       
   128   for (int index = 0; index < list->length(); index++) {
       
   129     PerfData* item = list->at(index);
       
   130     item->sample();
       
   131   }
       
   132 }
       
   133 
       
   134 /*
       
   135  * the collect_sample() method is the method invoked by the
       
   136  * WatcherThread via the PeriodicTask::task() method. This method
       
   137  * is responsible for collecting data samples from sampled
       
   138  * PerfData instances every PerfDataSamplingInterval milliseconds.
       
   139  * It is also responsible for logging the requested set of
       
   140  * PerfData instances every _sample_count milliseconds. While
       
   141  * logging data, it will output a column header after every _print_header
       
   142  * rows of data have been logged.
       
   143  */
       
   144 void StatSampler::collect_sample() {
       
   145 
       
   146   // future - check for new PerfData objects. PerfData objects might
       
   147   // get added to the PerfDataManager lists after we have already
       
   148   // built our local copies.
       
   149   //
       
   150   // if (PerfDataManager::count() > previous) {
       
   151   //   // get a new copy of the sampled list
       
   152   //   if (_sampled != NULL) {
       
   153   //     delete(_sampled);
       
   154   //     _sampled = NULL;
       
   155   //   }
       
   156   //   _sampled = PerfDataManager::sampled();
       
   157   // }
       
   158 
       
   159   assert(_sampled != NULL, "list not initialized");
       
   160 
       
   161   sample_data(_sampled);
       
   162 }
       
   163 
       
   164 /*
       
   165  * method to upcall into Java to return the value of the specified
       
   166  * property as a utf8 string, or NULL if does not exist. The caller
       
   167  * is responsible for setting a ResourceMark for proper cleanup of
       
   168  * the utf8 strings.
       
   169  */
       
   170 const char* StatSampler::get_system_property(const char* name, TRAPS) {
       
   171 
       
   172   // setup the arguments to getProperty
       
   173   Handle key_str   = java_lang_String::create_from_str(name, CHECK_NULL);
       
   174 
       
   175   // return value
       
   176   JavaValue result(T_OBJECT);
       
   177 
       
   178   // public static String getProperty(String key, String def);
       
   179   JavaCalls::call_static(&result,
       
   180                          KlassHandle(THREAD, SystemDictionary::system_klass()),
       
   181                          vmSymbolHandles::getProperty_name(),
       
   182                          vmSymbolHandles::string_string_signature(),
       
   183                          key_str,
       
   184                          CHECK_NULL);
       
   185 
       
   186   oop value_oop = (oop)result.get_jobject();
       
   187   if (value_oop == NULL) {
       
   188     return NULL;
       
   189   }
       
   190 
       
   191   // convert Java String to utf8 string
       
   192   char* value = java_lang_String::as_utf8_string(value_oop);
       
   193 
       
   194   return value;
       
   195 }
       
   196 
       
   197 /*
       
   198  * The list of System Properties that have corresponding PerfData
       
   199  * string instrumentation created by retrieving the named property's
       
   200  * value from System.getProperty() and unconditionally creating a
       
   201  * PerfStringConstant object initialized to the retreived value. This
       
   202  * is not an exhustive list of Java properties with corresponding string
       
   203  * instrumentation as the create_system_property_instrumentation() method
       
   204  * creates other property based instrumentation conditionally.
       
   205  */
       
   206 
       
   207 // stable interface, supported counters
       
   208 static const char* property_counters_ss[] = {
       
   209   "java.vm.specification.version",
       
   210   "java.vm.specification.name",
       
   211   "java.vm.specification.vendor",
       
   212   "java.vm.version",
       
   213   "java.vm.name",
       
   214   "java.vm.vendor",
       
   215   "java.vm.info",
       
   216   "java.library.path",
       
   217   "java.class.path",
       
   218   "java.endorsed.dirs",
       
   219   "java.ext.dirs",
       
   220   "java.home",
       
   221   NULL
       
   222 };
       
   223 
       
   224 // unstable interface, supported counters
       
   225 static const char* property_counters_us[] = {
       
   226   NULL
       
   227 };
       
   228 
       
   229 // unstable interface, unsupported counters
       
   230 static const char* property_counters_uu[] = {
       
   231   "sun.boot.class.path",
       
   232   "sun.boot.library.path",
       
   233   NULL
       
   234 };
       
   235 
       
   236 typedef struct {
       
   237   const char** property_list;
       
   238   CounterNS name_space;
       
   239 } PropertyCounters;
       
   240 
       
   241 static PropertyCounters property_counters[] = {
       
   242   { property_counters_ss, JAVA_PROPERTY },
       
   243   { property_counters_us, COM_PROPERTY },
       
   244   { property_counters_uu, SUN_PROPERTY },
       
   245   { NULL, SUN_PROPERTY }
       
   246 };
       
   247 
       
   248 
       
   249 /*
       
   250  * Method to create PerfData string instruments that contain the values
       
   251  * of various system properties. String instruments are created for each
       
   252  * property specified in the property lists provided in property_counters[].
       
   253  * Property counters have a counter name space prefix prepended to the
       
   254  * property name as indicated in property_counters[].
       
   255  */
       
   256 void StatSampler::create_system_property_instrumentation(TRAPS) {
       
   257 
       
   258   ResourceMark rm;
       
   259 
       
   260   for (int i = 0; property_counters[i].property_list != NULL; i++) {
       
   261 
       
   262     for (int j = 0; property_counters[i].property_list[j] != NULL; j++) {
       
   263 
       
   264       const char* property_name = property_counters[i].property_list[j];
       
   265       assert(property_name != NULL, "property name should not be NULL");
       
   266 
       
   267       const char* value = get_system_property(property_name, CHECK);
       
   268 
       
   269       // the property must exist
       
   270       assert(value != NULL, "property name should be valid");
       
   271 
       
   272       if (value != NULL) {
       
   273         // create the property counter
       
   274         PerfDataManager::create_string_constant(property_counters[i].name_space,
       
   275                                                 property_name, value, CHECK);
       
   276       }
       
   277     }
       
   278   }
       
   279 }
       
   280 
       
   281 /*
       
   282  * The create_misc_perfdata() method provides a place to create
       
   283  * PerfData instances that would otherwise have no better place
       
   284  * to exist.
       
   285  */
       
   286 void StatSampler::create_misc_perfdata() {
       
   287 
       
   288   ResourceMark rm;
       
   289   EXCEPTION_MARK;
       
   290 
       
   291   // numeric constants
       
   292 
       
   293   // frequency of the native high resolution timer
       
   294   PerfDataManager::create_constant(SUN_OS, "hrt.frequency",
       
   295                                    PerfData::U_Hertz, os::elapsed_frequency(),
       
   296                                    CHECK);
       
   297 
       
   298   // string constants
       
   299 
       
   300   // create string instrumentation for various Java properties.
       
   301   create_system_property_instrumentation(CHECK);
       
   302 
       
   303   // hotspot flags (from .hotspotrc) and args (from command line)
       
   304   //
       
   305   PerfDataManager::create_string_constant(JAVA_RT, "vmFlags",
       
   306                                           Arguments::jvm_flags(), CHECK);
       
   307   PerfDataManager::create_string_constant(JAVA_RT, "vmArgs",
       
   308                                           Arguments::jvm_args(), CHECK);
       
   309 
       
   310   // java class name/jar file and arguments to main class
       
   311   // note: name is cooridnated with launcher and Arguments.cpp
       
   312   PerfDataManager::create_string_constant(SUN_RT, "javaCommand",
       
   313                                           Arguments::java_command(), CHECK);
       
   314 
       
   315   // the Java VM Internal version string
       
   316   PerfDataManager::create_string_constant(SUN_RT, "internalVersion",
       
   317                                          VM_Version::internal_vm_info_string(),
       
   318                                          CHECK);
       
   319 
       
   320   // create sampled instrumentation objects
       
   321   create_sampled_perfdata();
       
   322 }
       
   323 
       
   324 /*
       
   325  * helper class to provide for sampling of the elapsed_counter value
       
   326  * maintained in the OS class.
       
   327  */
       
   328 class HighResTimeSampler : public PerfSampleHelper {
       
   329   public:
       
   330     jlong take_sample() { return os::elapsed_counter(); }
       
   331 };
       
   332 
       
   333 /*
       
   334  * the create_sampled_perdata() method provides a place to instantiate
       
   335  * sampled PerfData instances that would otherwise have no better place
       
   336  * to exist.
       
   337  */
       
   338 void StatSampler::create_sampled_perfdata() {
       
   339 
       
   340   EXCEPTION_MARK;
       
   341 
       
   342   // setup sampling of the elapsed time counter maintained in the
       
   343   // the os class. This counter can be used as either a time stamp
       
   344   // for each logged entry or as a liveness indicator for the VM.
       
   345   PerfSampleHelper* psh = new HighResTimeSampler();
       
   346   PerfDataManager::create_counter(SUN_OS, "hrt.ticks",
       
   347                                   PerfData::U_Ticks, psh, CHECK);
       
   348 }
       
   349 
       
   350 /*
       
   351  * the statSampler_exit() function is called from os_init.cpp on
       
   352  * exit of the vm.
       
   353  */
       
   354 void statSampler_exit() {
       
   355 
       
   356   if (!UsePerfData) return;
       
   357 
       
   358   StatSampler::destroy();
       
   359 }