< prev index next >

src/hotspot/share/runtime/heapMonitoring.cpp

Print this page
rev 47590 : [mq]: heap8
rev 47591 : [mq]: heap10a
rev 47592 : [mq]: heap14_rebased


 192   // of stack traces. Passes a jvmtiStackTraces which will get mutated.
 193   void get_garbage_stack_traces(jvmtiStackTraces *traces);
 194 
 195   // The function that gets called by the client to retrieve the list
 196   // of stack traces. Passes a jvmtiStackTraces which will get mutated.
 197   void get_frequent_garbage_stack_traces(jvmtiStackTraces *traces);
 198 
 199   // Executes whenever weak references are traversed.  is_alive tells
 200   // you if the given oop is still reachable and live.
 201   void weak_oops_do(BoolObjectClosure* is_alive, OopClosure *f);
 202 
 203   ~StackTraceStorage();
 204   StackTraceStorage();
 205 
 206   static StackTraceStorage* storage() {
 207     static StackTraceStorage internal_storage;
 208     return &internal_storage;
 209   }
 210 
 211   void initialize(int max_storage) {
 212     MutexLocker mu(HeapMonitor_lock);
 213     free_storage();
 214     allocate_storage(max_storage);
 215     memset(&_stats, 0, sizeof(_stats));
 216   }
 217 
 218   const jvmtiHeapSamplingStats& get_heap_sampling_stats() const {
 219     return _stats;
 220   }
 221 
 222   void accumulate_sample_rate(size_t rate) {
 223     _stats.sample_rate_accumulation += rate;
 224     _stats.sample_rate_count++;
 225   }
 226 
 227   bool initialized() { return _initialized; }
 228 
 229  private:
 230   // The traces currently sampled.
 231   GrowableArray<StackTraceData> *_allocated_traces;
 232 


 278 
 279   // Copies from StackTraceData to jvmtiStackTrace.
 280   bool deep_copy(jvmtiStackTrace *to, const StackTraceData *from);
 281 
 282   // Creates a deep copy of the list of StackTraceData.
 283   void copy_stack_traces(const StackTraceDataCopier &copier,
 284                          jvmtiStackTraces *traces);
 285 
 286   void store_garbage_trace(const StackTraceData &trace);
 287 
 288   void free_garbage();
 289   void free_storage();
 290   void allocate_storage(int max_gc_storage);
 291 };
 292 
 293 StackTraceStorage* StackTraceStorage::internal_storage;
 294 
 295 // Statics for Sampler
 296 double HeapMonitoring::_log_table[1 << FastLogNumBits];
 297 bool HeapMonitoring::_enabled;
 298 AlwaysTrueClosure HeapMonitoring::_always_true;
 299 jint HeapMonitoring::_monitoring_rate;
 300 
 301 // Cheap random number generator
 302 uint64_t HeapMonitoring::_rnd;
 303 
 304 StackTraceStorage::StackTraceStorage() :
 305   _allocated_traces(NULL),
 306   _recent_garbage_traces(NULL),
 307   _frequent_garbage_traces(NULL),
 308   _max_gc_storage(0),
 309   _initialized(false) {
 310 }
 311 
 312 void StackTraceStorage::free_garbage() {
 313   StackTraceData **recent_garbage = NULL;
 314   uint32_t recent_size = 0;
 315 
 316   StackTraceData **frequent_garbage = NULL;
 317   uint32_t frequent_size = 0;
 318 


 365   free_storage();
 366 }
 367 
 368 void StackTraceStorage::allocate_storage(int max_gc_storage) {
 369   // In case multiple threads got locked and then 1 by 1 got through.
 370   if (_initialized) {
 371     return;
 372   }
 373 
 374   _allocated_traces = new (ResourceObj::C_HEAP, mtInternal)
 375       GrowableArray<StackTraceData>(128, true);
 376 
 377   _recent_garbage_traces = new MostRecentGarbageTraces(max_gc_storage);
 378   _frequent_garbage_traces = new FrequentGarbageTraces(max_gc_storage);
 379 
 380   _max_gc_storage = max_gc_storage;
 381   _initialized = true;
 382 }
 383 
 384 void StackTraceStorage::add_trace(jvmtiStackTrace *trace, oop o) {
 385   MutexLocker mu(HeapMonitor_lock);
 386   StackTraceData new_data(trace, o);
 387   _stats.sample_count++;
 388   _stats.stack_depth_accumulation += trace->frame_count;
 389   _allocated_traces->append(new_data);
 390 }
 391 
 392 void StackTraceStorage::weak_oops_do(BoolObjectClosure *is_alive,
 393                                      OopClosure *f) {
 394   MutexLocker mu(HeapMonitor_lock);
 395   size_t count = 0;
 396   if (initialized()) {
 397     int len = _allocated_traces->length();
 398 
 399     // Compact the oop traces.  Moves the live oops to the beginning of the
 400     // growable array, potentially overwriting the dead ones.
 401     int curr_pos = 0;
 402     for (int i = 0; i < len; i++) {
 403       StackTraceData &trace = _allocated_traces->at(i);
 404       oop value = trace.obj;
 405       if (Universe::heap()->is_in_reserved(value)
 406           && is_alive->do_object_b(value)) {
 407         // Update the oop to point to the new object if it is still alive.
 408         f->do_oop(&(trace.obj));
 409 
 410         // Copy the old trace, if it is still live.
 411         _allocated_traces->at_put(curr_pos++, trace);
 412 
 413         count++;
 414       } else {


 459 }
 460 
 461 // See comment on get_all_stack_traces
 462 void StackTraceStorage::get_garbage_stack_traces(jvmtiStackTraces *traces) {
 463   GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(),
 464                                      _recent_garbage_traces->size());
 465   copy_stack_traces(copier, traces);
 466 }
 467 
 468 // See comment on get_all_stack_traces
 469 void StackTraceStorage::get_frequent_garbage_stack_traces(
 470     jvmtiStackTraces *traces) {
 471   GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(),
 472                                      _frequent_garbage_traces->size());
 473   copy_stack_traces(copier, traces);
 474 }
 475 
 476 
 477 void StackTraceStorage::copy_stack_traces(const StackTraceDataCopier &copier,
 478                                           jvmtiStackTraces *traces) {
 479   MutexLocker mu(HeapMonitor_lock);
 480   int len = copier.size();
 481 
 482   // Create a new array to store the StackTraceData objects.
 483   // + 1 for a NULL at the end.
 484   jvmtiStackTrace *t =
 485       NEW_C_HEAP_ARRAY(jvmtiStackTrace, len + 1, mtInternal);
 486   if (t == NULL) {
 487     traces->stack_traces = NULL;
 488     traces->trace_count = 0;
 489     return;
 490   }
 491   // +1 to have a NULL at the end of the array.
 492   memset(t, 0, (len + 1) * sizeof(*t));
 493 
 494   // Copy the StackTraceData objects into the new array.
 495   int trace_count = 0;
 496   for (int i = 0; i < len; i++) {
 497     const StackTraceData *stack_trace = copier.get(i);
 498     if (stack_trace != NULL) {
 499       jvmtiStackTrace *to = &t[trace_count];


 549 
 550   for (jint i = 0; i < trace_count; i++) {
 551     jvmtiStackTrace *current_trace = stack_traces + i;
 552     FREE_C_HEAP_ARRAY(jvmtiFrameInfo, current_trace->frames);
 553   }
 554 
 555   FREE_C_HEAP_ARRAY(jvmtiStackTrace, traces->stack_traces);
 556   traces->trace_count = 0;
 557   traces->stack_traces = NULL;
 558 }
 559 
 560 // Invoked by the GC to clean up old stack traces and remove old arrays
 561 // of instrumentation that are still lying around.
 562 void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure *f) {
 563   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 564   StackTraceStorage::storage()->weak_oops_do(is_alive, f);
 565 }
 566 
 567 void HeapMonitoring::initialize_profiling(jint monitoring_rate,
 568                                           jint max_gc_storage) {

 569   // Ignore if already enabled.
 570   if (_enabled) {
 571     return;
 572   }
 573 
 574   _monitoring_rate = monitoring_rate;
 575 
 576   // Populate the lookup table for fast_log2.
 577   // This approximates the log2 curve with a step function.
 578   // Steps have height equal to log2 of the mid-point of the step.
 579   for (int i = 0; i < (1 << FastLogNumBits); i++) {
 580     double half_way = static_cast<double>(i + 0.5);
 581     _log_table[i] = (log(1.0 + half_way / (1 << FastLogNumBits)) / log(2.0));
 582   }
 583 
 584   JavaThread *t = static_cast<JavaThread *>(Thread::current());
 585   _rnd = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(t));
 586   if (_rnd == 0) {
 587     _rnd = 1;
 588   }
 589 
 590   StackTraceStorage::storage()->initialize(max_gc_storage);
 591   _enabled = true;
 592 }
 593 
 594 void HeapMonitoring::stop_profiling() {

 595   _enabled = false;
 596 }
 597 
 598 // Generates a geometric variable with the specified mean (512K by default).
 599 // This is done by generating a random number between 0 and 1 and applying
 600 // the inverse cumulative distribution function for an exponential.
 601 // Specifically: Let m be the inverse of the sample rate, then
 602 // the probability distribution function is m*exp(-mx) so the CDF is
 603 // p = 1 - exp(-mx), so
 604 // q = 1 - p = exp(-mx)
 605 // log_e(q) = -mx
 606 // -log_e(q)/m = x
 607 // log_2(q) * (-log_e(2) * 1/m) = x
 608 // In the code, q is actually in the range 1 to 2**26, hence the -26 below
 609 void HeapMonitoring::pick_next_sample(size_t *ptr) {
 610   _rnd = next_random(_rnd);
 611   // Take the top 26 bits as the random number
 612   // (This plus a 1<<58 sampling bound gives a max possible step of
 613   // 5194297183973780480 bytes.  In this case,
 614   // for sample_parameter = 1<<19, max possible step is
 615   // 9448372 bytes (24 bits).
 616   const uint64_t prng_mod_power = 48;  // Number of bits in prng
 617   // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
 618   // under piii debug for some binaries.
 619   double q = static_cast<uint32_t>(_rnd >> (prng_mod_power - 26)) + 1.0;
 620   // Put the computed p-value through the CDF of a geometric.
 621   // For faster performance (save ~1/20th exec time), replace
 622   // min(0.0, FastLog2(q) - 26)  by  (Fastlog2(q) - 26.000705)
 623   // The value 26.000705 is used rather than 26 to compensate
 624   // for inaccuracies in FastLog2 which otherwise result in a
 625   // negative answer.
 626   double log_val = (fast_log2(q) - 26);
 627   size_t rate = static_cast<size_t>(
 628       (0.0 < log_val ? 0.0 : log_val) * (-log(2.0) * (_monitoring_rate)) + 1);
 629   *ptr = rate;
 630 
 631   StackTraceStorage::storage()->accumulate_sample_rate(rate);
 632 }
 633 
 634 void HeapMonitoring::object_alloc_do_sample(Thread *t, oopDesc *o, intx byte_size) {
 635 #if defined(X86) || defined(PPC)
 636   JavaThread *thread = static_cast<JavaThread *>(t);
 637   if (StackTraceStorage::storage()->initialized()) {
 638     assert(t->is_Java_thread(), "non-Java thread passed to do_sample");
 639     JavaThread *thread = static_cast<JavaThread *>(t);




 192   // of stack traces. Passes a jvmtiStackTraces which will get mutated.
 193   void get_garbage_stack_traces(jvmtiStackTraces *traces);
 194 
 195   // The function that gets called by the client to retrieve the list
 196   // of stack traces. Passes a jvmtiStackTraces which will get mutated.
 197   void get_frequent_garbage_stack_traces(jvmtiStackTraces *traces);
 198 
 199   // Executes whenever weak references are traversed.  is_alive tells
 200   // you if the given oop is still reachable and live.
 201   void weak_oops_do(BoolObjectClosure* is_alive, OopClosure *f);
 202 
 203   ~StackTraceStorage();
 204   StackTraceStorage();
 205 
 206   static StackTraceStorage* storage() {
 207     static StackTraceStorage internal_storage;
 208     return &internal_storage;
 209   }
 210 
 211   void initialize(int max_storage) {
 212     MutexLocker mu(HeapMonitorStorage_lock);
 213     free_storage();
 214     allocate_storage(max_storage);
 215     memset(&_stats, 0, sizeof(_stats));
 216   }
 217 
 218   const jvmtiHeapSamplingStats& get_heap_sampling_stats() const {
 219     return _stats;
 220   }
 221 
 222   void accumulate_sample_rate(size_t rate) {
 223     _stats.sample_rate_accumulation += rate;
 224     _stats.sample_rate_count++;
 225   }
 226 
 227   bool initialized() { return _initialized; }
 228 
 229  private:
 230   // The traces currently sampled.
 231   GrowableArray<StackTraceData> *_allocated_traces;
 232 


 278 
 279   // Copies from StackTraceData to jvmtiStackTrace.
 280   bool deep_copy(jvmtiStackTrace *to, const StackTraceData *from);
 281 
 282   // Creates a deep copy of the list of StackTraceData.
 283   void copy_stack_traces(const StackTraceDataCopier &copier,
 284                          jvmtiStackTraces *traces);
 285 
 286   void store_garbage_trace(const StackTraceData &trace);
 287 
 288   void free_garbage();
 289   void free_storage();
 290   void allocate_storage(int max_gc_storage);
 291 };
 292 
 293 StackTraceStorage* StackTraceStorage::internal_storage;
 294 
 295 // Statics for Sampler
 296 double HeapMonitoring::_log_table[1 << FastLogNumBits];
 297 bool HeapMonitoring::_enabled;

 298 jint HeapMonitoring::_monitoring_rate;
 299 
 300 // Cheap random number generator
 301 uint64_t HeapMonitoring::_rnd;
 302 
 303 StackTraceStorage::StackTraceStorage() :
 304   _allocated_traces(NULL),
 305   _recent_garbage_traces(NULL),
 306   _frequent_garbage_traces(NULL),
 307   _max_gc_storage(0),
 308   _initialized(false) {
 309 }
 310 
 311 void StackTraceStorage::free_garbage() {
 312   StackTraceData **recent_garbage = NULL;
 313   uint32_t recent_size = 0;
 314 
 315   StackTraceData **frequent_garbage = NULL;
 316   uint32_t frequent_size = 0;
 317 


 364   free_storage();
 365 }
 366 
 367 void StackTraceStorage::allocate_storage(int max_gc_storage) {
 368   // In case multiple threads got locked and then 1 by 1 got through.
 369   if (_initialized) {
 370     return;
 371   }
 372 
 373   _allocated_traces = new (ResourceObj::C_HEAP, mtInternal)
 374       GrowableArray<StackTraceData>(128, true);
 375 
 376   _recent_garbage_traces = new MostRecentGarbageTraces(max_gc_storage);
 377   _frequent_garbage_traces = new FrequentGarbageTraces(max_gc_storage);
 378 
 379   _max_gc_storage = max_gc_storage;
 380   _initialized = true;
 381 }
 382 
 383 void StackTraceStorage::add_trace(jvmtiStackTrace *trace, oop o) {
 384   MutexLocker mu(HeapMonitorStorage_lock);
 385   StackTraceData new_data(trace, o);
 386   _stats.sample_count++;
 387   _stats.stack_depth_accumulation += trace->frame_count;
 388   _allocated_traces->append(new_data);
 389 }
 390 
 391 void StackTraceStorage::weak_oops_do(BoolObjectClosure *is_alive,
 392                                      OopClosure *f) {
 393   MutexLocker mu(HeapMonitorStorage_lock);
 394   size_t count = 0;
 395   if (initialized()) {
 396     int len = _allocated_traces->length();
 397 
 398     // Compact the oop traces.  Moves the live oops to the beginning of the
 399     // growable array, potentially overwriting the dead ones.
 400     int curr_pos = 0;
 401     for (int i = 0; i < len; i++) {
 402       StackTraceData &trace = _allocated_traces->at(i);
 403       oop value = trace.obj;
 404       if (Universe::heap()->is_in_reserved(value)
 405           && is_alive->do_object_b(value)) {
 406         // Update the oop to point to the new object if it is still alive.
 407         f->do_oop(&(trace.obj));
 408 
 409         // Copy the old trace, if it is still live.
 410         _allocated_traces->at_put(curr_pos++, trace);
 411 
 412         count++;
 413       } else {


 458 }
 459 
 460 // See comment on get_all_stack_traces
 461 void StackTraceStorage::get_garbage_stack_traces(jvmtiStackTraces *traces) {
 462   GarbageStackTraceDataCopier copier(_recent_garbage_traces->get_traces(),
 463                                      _recent_garbage_traces->size());
 464   copy_stack_traces(copier, traces);
 465 }
 466 
 467 // See comment on get_all_stack_traces
 468 void StackTraceStorage::get_frequent_garbage_stack_traces(
 469     jvmtiStackTraces *traces) {
 470   GarbageStackTraceDataCopier copier(_frequent_garbage_traces->get_traces(),
 471                                      _frequent_garbage_traces->size());
 472   copy_stack_traces(copier, traces);
 473 }
 474 
 475 
 476 void StackTraceStorage::copy_stack_traces(const StackTraceDataCopier &copier,
 477                                           jvmtiStackTraces *traces) {
 478   MutexLocker mu(HeapMonitorStorage_lock);
 479   int len = copier.size();
 480 
 481   // Create a new array to store the StackTraceData objects.
 482   // + 1 for a NULL at the end.
 483   jvmtiStackTrace *t =
 484       NEW_C_HEAP_ARRAY(jvmtiStackTrace, len + 1, mtInternal);
 485   if (t == NULL) {
 486     traces->stack_traces = NULL;
 487     traces->trace_count = 0;
 488     return;
 489   }
 490   // +1 to have a NULL at the end of the array.
 491   memset(t, 0, (len + 1) * sizeof(*t));
 492 
 493   // Copy the StackTraceData objects into the new array.
 494   int trace_count = 0;
 495   for (int i = 0; i < len; i++) {
 496     const StackTraceData *stack_trace = copier.get(i);
 497     if (stack_trace != NULL) {
 498       jvmtiStackTrace *to = &t[trace_count];


 548 
 549   for (jint i = 0; i < trace_count; i++) {
 550     jvmtiStackTrace *current_trace = stack_traces + i;
 551     FREE_C_HEAP_ARRAY(jvmtiFrameInfo, current_trace->frames);
 552   }
 553 
 554   FREE_C_HEAP_ARRAY(jvmtiStackTrace, traces->stack_traces);
 555   traces->trace_count = 0;
 556   traces->stack_traces = NULL;
 557 }
 558 
 559 // Invoked by the GC to clean up old stack traces and remove old arrays
 560 // of instrumentation that are still lying around.
 561 void HeapMonitoring::weak_oops_do(BoolObjectClosure* is_alive, OopClosure *f) {
 562   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 563   StackTraceStorage::storage()->weak_oops_do(is_alive, f);
 564 }
 565 
 566 void HeapMonitoring::initialize_profiling(jint monitoring_rate,
 567                                           jint max_gc_storage) {
 568   MutexLocker mu(HeapMonitor_lock);
 569   // Ignore if already enabled.
 570   if (_enabled) {
 571     return;
 572   }
 573 
 574   _monitoring_rate = monitoring_rate;
 575 
 576   // Populate the lookup table for fast_log2.
 577   // This approximates the log2 curve with a step function.
 578   // Steps have height equal to log2 of the mid-point of the step.
 579   for (int i = 0; i < (1 << FastLogNumBits); i++) {
 580     double half_way = static_cast<double>(i + 0.5);
 581     _log_table[i] = (log(1.0 + half_way / (1 << FastLogNumBits)) / log(2.0));
 582   }
 583 
 584   JavaThread *t = static_cast<JavaThread *>(Thread::current());
 585   _rnd = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(t));
 586   if (_rnd == 0) {
 587     _rnd = 1;
 588   }
 589 
 590   StackTraceStorage::storage()->initialize(max_gc_storage);
 591   _enabled = true;
 592 }
 593 
 594 void HeapMonitoring::stop_profiling() {
 595   MutexLocker mu(HeapMonitor_lock);
 596   _enabled = false;
 597 }
 598 
 599 // Generates a geometric variable with the specified mean (512K by default).
 600 // This is done by generating a random number between 0 and 1 and applying
 601 // the inverse cumulative distribution function for an exponential.
 602 // Specifically: Let m be the inverse of the sample rate, then
 603 // the probability distribution function is m*exp(-mx) so the CDF is
 604 // p = 1 - exp(-mx), so
 605 // q = 1 - p = exp(-mx)
 606 // log_e(q) = -mx
 607 // -log_e(q)/m = x
 608 // log_2(q) * (-log_e(2) * 1/m) = x
 609 // In the code, q is actually in the range 1 to 2**26, hence the -26 below
 610 void HeapMonitoring::pick_next_sample(size_t *ptr) {
 611   _rnd = next_random(_rnd);
 612   // Take the top 26 bits as the random number
 613   // (This plus a 1<<58 sampling bound gives a max possible step of
 614   // 5194297183973780480 bytes.  In this case,
 615   // for sample_parameter = 1<<19, max possible step is
 616   // 9448372 bytes (24 bits).
 617   const uint64_t PrngModPower = 48;  // Number of bits in prng
 618   // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
 619   // under piii debug for some binaries.
 620   double q = static_cast<uint32_t>(_rnd >> (PrngModPower - 26)) + 1.0;
 621   // Put the computed p-value through the CDF of a geometric.
 622   // For faster performance (save ~1/20th exec time), replace
 623   // min(0.0, FastLog2(q) - 26)  by  (Fastlog2(q) - 26.000705)
 624   // The value 26.000705 is used rather than 26 to compensate
 625   // for inaccuracies in FastLog2 which otherwise result in a
 626   // negative answer.
 627   double log_val = (fast_log2(q) - 26);
 628   size_t rate = static_cast<size_t>(
 629       (0.0 < log_val ? 0.0 : log_val) * (-log(2.0) * (_monitoring_rate)) + 1);
 630   *ptr = rate;
 631 
 632   StackTraceStorage::storage()->accumulate_sample_rate(rate);
 633 }
 634 
 635 void HeapMonitoring::object_alloc_do_sample(Thread *t, oopDesc *o, intx byte_size) {
 636 #if defined(X86) || defined(PPC)
 637   JavaThread *thread = static_cast<JavaThread *>(t);
 638   if (StackTraceStorage::storage()->initialized()) {
 639     assert(t->is_Java_thread(), "non-Java thread passed to do_sample");
 640     JavaThread *thread = static_cast<JavaThread *>(t);


< prev index next >