< prev index next >

src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp

Print this page
rev 8911 : [jfr] enable thread sampling


 304   _self(Thread::current()),
 305   _added_java(0),
 306   _added_native(0) {
 307 }
 308 
 309 class JfrThreadSampler : public Thread {
 310   friend class JfrThreadSampling;
 311  private:
 312   Semaphore _sample;
 313   Thread* _sampler_thread;
 314   JfrStackFrame* const _frames;
 315   JavaThread* _last_thread_java;
 316   JavaThread* _last_thread_native;
 317   size_t _interval_java;
 318   size_t _interval_native;
 319   int _cur_index;
 320   const u4 _max_frames;
 321   volatile bool _disenrolled;
 322   static Monitor* _transition_block_lock;
 323 
 324 //  JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current);

 325   void task_stacktrace(JfrSampleType type, JavaThread** last_thread);
 326   JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames);
 327   ~JfrThreadSampler();
 328 
 329   void start_thread();
 330 
 331   void enroll();
 332   void disenroll();
 333   void set_java_interval(size_t interval) { _interval_java = interval; };
 334   void set_native_interval(size_t interval) { _interval_native = interval; };
 335   size_t get_java_interval() { return _interval_java; };
 336   size_t get_native_interval() { return _interval_native; };
 337 
 338  public:
 339   void run();
 340   static Monitor* transition_block() { return _transition_block_lock; }
 341   static void on_javathread_suspend(JavaThread* thread);
 342 };
 343 
 344 Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);
 345 
 346 static void clear_transition_block(JavaThread* jt) {
 347 //  jt->clear_trace_flag();
 348   JfrThreadLocal* const tl = jt->jfr_thread_local();
 349   if (tl->is_trace_block()) {
 350     MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
 351     JfrThreadSampler::transition_block()->notify_all();
 352   }
 353 }
 354 
 355 bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
 356   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 357   if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
 358     return false;
 359   }
 360 
 361   bool ret = false;
 362 //  thread->set_trace_flag();
 363   if (!UseMembar) {
 364     os::serialize_thread_states();
 365   }
 366   if (JAVA_SAMPLE == type) {
 367     if (thread_state_in_java(thread)) {
 368       ret = sample_thread_in_java(thread, frames, max_frames);
 369     }
 370   } else {
 371     assert(NATIVE_SAMPLE == type, "invariant");
 372     if (thread_state_in_native(thread)) {
 373       ret = sample_thread_in_native(thread, frames, max_frames);
 374     }
 375   }
 376   clear_transition_block(thread);
 377   return ret;
 378 }
 379 
 380 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
 381   _sample(),
 382   _sampler_thread(NULL),
 383   _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
 384   _last_thread_java(NULL),
 385   _last_thread_native(NULL),
 386   _interval_java(interval_java),
 387   _interval_native(interval_native),
 388   _cur_index(-1),
 389   _max_frames(max_frames),
 390   _disenrolled(true) {
 391 }
 392 
 393 JfrThreadSampler::~JfrThreadSampler() {
 394   JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
 395 }
 396 
 397 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
 398   JfrThreadLocal* const tl = thread->jfr_thread_local();
 399   tl->set_trace_block();
 400   {
 401 //    MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
 402 //    while (thread->is_trace_suspend()) {
 403 //      transition_block()->wait(true);
 404 //    }
 405 //    tl->clear_trace_block();
 406   }















 407 }
 408 
 409 //JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
 410 //  assert(t_list != NULL, "invariant");
 411 //  assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 412 //  assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
 413 //  assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
 414 //  if ((uint)_cur_index + 1 == t_list->length()) {
 415 //    // wrap
 416 //    _cur_index = 0;
 417 //  } else {
 418 //    _cur_index++;
 419 //  }
 420 //  assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
 421 //  JavaThread* const next = t_list->thread_at(_cur_index);
 422 //  return next != first_sampled ? next : NULL;
 423 //}












 424 
 425 void JfrThreadSampler::start_thread() {
 426   // XXX TODO implement sampling
 427 //  if (os::create_thread(this, os::os_thread)) {
 428 //    os::start_thread(this);
 429 //  } else {
 430 //    if (true) tty->print_cr("Failed to create thread for thread sampling");
 431 //  }
 432 }
 433 
 434 void JfrThreadSampler::enroll() {
 435   if (_disenrolled) {
 436     if (LogJFR) tty->print_cr("Enrolling thread sampler");
 437     _sample.signal();
 438     _disenrolled = false;
 439   }
 440 }
 441 
 442 void JfrThreadSampler::disenroll() {
 443   if (!_disenrolled) {
 444     _sample.wait();
 445     _disenrolled = true;
 446     if (LogJFR) tty->print_cr("Disenrolling thread sampler");
 447   }
 448 }
 449 
 450 static jlong get_monotonic_ms() {
 451   return os::javaTimeNanos() / 1000000;


 492     }
 493   }
 494   delete this;
 495 }
 496 
 497 
 498 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
 499   ResourceMark rm;
 500   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
 501   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
 502   JfrThreadSampleClosure sample_task(samples, samples_native);
 503 
 504   const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
 505   uint num_sample_attempts = 0;
 506   JavaThread* start = NULL;
 507 
 508   {
 509     elapsedTimer sample_time;
 510     sample_time.start();
 511     {
 512 //      MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
 513 //      ThreadsListHandle tlh;
 514 //      // Resolve a sample session relative start position index into the thread list array.
 515 //      // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
 516 //      _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
 517 //      JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
 518 //
 519 //      while (num_sample_attempts < sample_limit) {
 520 //        current = next_thread(tlh.list(), start, current);
 521 //        if (current == NULL) {
 522 //          break;
 523 //        }
 524 //        if (start == NULL) {
 525 //          start = current;  // remember the thread where we started to attempt sampling
 526 //        }
 527 //        if (current->is_Compiler_thread()) {
 528 //          continue;
 529 //        }
 530 //        sample_task.do_sample_thread(current, _frames, _max_frames, type);
 531 //        num_sample_attempts++;
 532 //      }
 533 //      *last_thread = current;  // remember the thread we last attempted to sample





 534     }
 535     sample_time.stop();
 536     if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
 537                    sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
 538   }
 539   if (num_sample_attempts > 0) {
 540     sample_task.commit_events(type);
 541   }
 542 }
 543 
 544 static JfrThreadSampling* _instance = NULL;
 545 
 546 JfrThreadSampling& JfrThreadSampling::instance() {
 547   return *_instance;
 548 }
 549 
 550 JfrThreadSampling* JfrThreadSampling::create() {
 551   assert(_instance == NULL, "invariant");
 552   _instance = new JfrThreadSampling();
 553   return _instance;




 304   _self(Thread::current()),
 305   _added_java(0),
 306   _added_native(0) {
 307 }
 308 
 309 class JfrThreadSampler : public Thread {
 310   friend class JfrThreadSampling;
 311  private:
 312   Semaphore _sample;
 313   Thread* _sampler_thread;
 314   JfrStackFrame* const _frames;
 315   JavaThread* _last_thread_java;
 316   JavaThread* _last_thread_native;
 317   size_t _interval_java;
 318   size_t _interval_native;
 319   int _cur_index;
 320   const u4 _max_frames;
 321   volatile bool _disenrolled;
 322   static Monitor* _transition_block_lock;
 323 
 324   int find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target);
 325   JavaThread* next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current);
 326   void task_stacktrace(JfrSampleType type, JavaThread** last_thread);
 327   JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames);
 328   ~JfrThreadSampler();
 329 
 330   void start_thread();
 331 
 332   void enroll();
 333   void disenroll();
 334   void set_java_interval(size_t interval) { _interval_java = interval; };
 335   void set_native_interval(size_t interval) { _interval_native = interval; };
 336   size_t get_java_interval() { return _interval_java; };
 337   size_t get_native_interval() { return _interval_native; };
 338 
 339  public:
 340   void run();
 341   static Monitor* transition_block() { return _transition_block_lock; }
 342   static void on_javathread_suspend(JavaThread* thread);
 343 };
 344 
 345 Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);
 346 
 347 static void clear_transition_block(JavaThread* jt) {
 348   jt->clear_trace_flag();
 349   JfrThreadLocal* const tl = jt->jfr_thread_local();
 350   if (tl->is_trace_block()) {
 351     MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
 352     JfrThreadSampler::transition_block()->notify_all();
 353   }
 354 }
 355 
 356 bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
 357   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 358   if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
 359     return false;
 360   }
 361 
 362   bool ret = false;
 363   thread->set_trace_flag();
 364   if (!UseMembar) {
 365     os::serialize_thread_states();
 366   }
 367   if (JAVA_SAMPLE == type) {
 368     if (thread_state_in_java(thread)) {
 369       ret = sample_thread_in_java(thread, frames, max_frames);
 370     }
 371   } else {
 372     assert(NATIVE_SAMPLE == type, "invariant");
 373     if (thread_state_in_native(thread)) {
 374       ret = sample_thread_in_native(thread, frames, max_frames);
 375     }
 376   }
 377   clear_transition_block(thread);
 378   return ret;
 379 }
 380 
 381 JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
 382   _sample(),
 383   _sampler_thread(NULL),
 384   _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
 385   _last_thread_java(NULL),
 386   _last_thread_native(NULL),
 387   _interval_java(interval_java),
 388   _interval_native(interval_native),
 389   _cur_index(-1),
 390   _max_frames(max_frames),
 391   _disenrolled(true) {
 392 }
 393 
 394 JfrThreadSampler::~JfrThreadSampler() {
 395   JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
 396 }
 397 
 398 void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
 399   JfrThreadLocal* const tl = thread->jfr_thread_local();
 400   tl->set_trace_block();
 401   {
 402     MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
 403     while (thread->is_trace_suspend()) {
 404       transition_block()->wait(true);


 405     }
 406     tl->clear_trace_block();
 407   }
 408 }
 409 
 410 int JfrThreadSampler::find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target) {
 411   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 412   if (target == NULL) {
 413     return -1;
 414   }
 415   for (uint i = 0; i < length; i++) {
 416     if (target == t_list[i]) {
 417       return (int)i;
 418     }
 419   }
 420   return -1;
 421 }
 422 
 423 JavaThread* JfrThreadSampler::next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current) {
 424   assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
 425   if (current == NULL) {
 426     _cur_index = 0;
 427     return t_list[_cur_index];
 428   }
 429 
 430   if (_cur_index == -1 || t_list[_cur_index] != current) {
 431     // 'current' is not at '_cur_index' so find it:
 432     _cur_index = find_index_of_JavaThread(t_list, length, current);
 433     assert(_cur_index != -1, "current JavaThread should be findable.");
 434   }
 435   _cur_index++;
 436 
 437   JavaThread* next = NULL;
 438   // wrap
 439   if ((uint)_cur_index >= length) {
 440     _cur_index = 0;
 441   }
 442   next = t_list[_cur_index];
 443 
 444   // sample wrap
 445   if (next == first_sampled) {
 446     return NULL;
 447   }
 448   return next;
 449 }
 450 
 451 void JfrThreadSampler::start_thread() {
 452   if (os::create_thread(this, os::os_thread)) {
 453     os::start_thread(this);
 454   } else {
 455     tty->print_cr("Failed to create thread for thread sampling");
 456   }

 457 }
 458 
 459 void JfrThreadSampler::enroll() {
 460   if (_disenrolled) {
 461     if (LogJFR) tty->print_cr("Enrolling thread sampler");
 462     _sample.signal();
 463     _disenrolled = false;
 464   }
 465 }
 466 
 467 void JfrThreadSampler::disenroll() {
 468   if (!_disenrolled) {
 469     _sample.wait();
 470     _disenrolled = true;
 471     if (LogJFR) tty->print_cr("Disenrolling thread sampler");
 472   }
 473 }
 474 
 475 static jlong get_monotonic_ms() {
 476   return os::javaTimeNanos() / 1000000;


 517     }
 518   }
 519   delete this;
 520 }
 521 
 522 
 523 void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
 524   ResourceMark rm;
 525   EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
 526   EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
 527   JfrThreadSampleClosure sample_task(samples, samples_native);
 528 
 529   const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
 530   uint num_sample_attempts = 0;
 531   JavaThread* start = NULL;
 532 
 533   {
 534     elapsedTimer sample_time;
 535     sample_time.start();
 536     {
 537       MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
 538       int max_threads = Threads::number_of_threads();
 539       assert(max_threads >= 0, "Threads list is empty");
 540       uint index = 0;
 541       JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal);
 542       for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
 543         threads_list[index++] = tp;
 544       }
 545       JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL;
 546       JavaThread* start = NULL;
 547 
 548       while (num_sample_attempts < sample_limit) {
 549         current = next_thread(threads_list, index, start, current);
 550         if (current == NULL) {
 551           break;
 552         }
 553         if (start == NULL) {
 554           start = current;  // remember the thread where we started to attempt sampling
 555         }
 556         if (current->is_Compiler_thread()) {
 557           continue;
 558         }
 559         sample_task.do_sample_thread(current, _frames, _max_frames, type);
 560         num_sample_attempts++;
 561       }
 562       *last_thread = current;  // remember the thread we last attempted to sample
 563       FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);
 564     }
 565     sample_time.stop();
 566     if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
 567                    sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
 568   }
 569   if (num_sample_attempts > 0) {
 570     sample_task.commit_events(type);
 571   }
 572 }
 573 
 574 static JfrThreadSampling* _instance = NULL;
 575 
 576 JfrThreadSampling& JfrThreadSampling::instance() {
 577   return *_instance;
 578 }
 579 
 580 JfrThreadSampling* JfrThreadSampling::create() {
 581   assert(_instance == NULL, "invariant");
 582   _instance = new JfrThreadSampling();
 583   return _instance;


< prev index next >