comparison src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @ 4095:bca17e38de00

6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads Summary: Select number of GC threads dynamically based on heap usage and number of Java threads Reviewed-by: johnc, ysr, jcoomes
author jmasa
date Tue, 09 Aug 2011 10:16:01 -0700
parents f95d63e2154a
children 6d7d0790074d
comparison
equal deleted inserted replaced
4094:3a298e04d914 4095:bca17e38de00
23 */ 23 */
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" 26 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp" 27 #include "gc_implementation/parallelScavenge/gcTaskThread.hpp"
28 #include "gc_implementation/shared/adaptiveSizePolicy.hpp"
28 #include "memory/allocation.hpp" 29 #include "memory/allocation.hpp"
29 #include "memory/allocation.inline.hpp" 30 #include "memory/allocation.inline.hpp"
30 #include "runtime/mutex.hpp" 31 #include "runtime/mutex.hpp"
31 #include "runtime/mutexLocker.hpp" 32 #include "runtime/mutexLocker.hpp"
32 33
179 } else { 180 } else {
180 insert_end()->set_newer(task); 181 insert_end()->set_newer(task);
181 } 182 }
182 set_insert_end(task); 183 set_insert_end(task);
183 increment_length(); 184 increment_length();
185 verify_length();
184 if (TraceGCTaskQueue) { 186 if (TraceGCTaskQueue) {
185 print("after:"); 187 print("after:");
186 } 188 }
187 } 189 }
188 190
190 void GCTaskQueue::enqueue(GCTaskQueue* list) { 192 void GCTaskQueue::enqueue(GCTaskQueue* list) {
191 if (TraceGCTaskQueue) { 193 if (TraceGCTaskQueue) {
192 tty->print_cr("[" INTPTR_FORMAT "]" 194 tty->print_cr("[" INTPTR_FORMAT "]"
193 " GCTaskQueue::enqueue(list: " 195 " GCTaskQueue::enqueue(list: "
194 INTPTR_FORMAT ")", 196 INTPTR_FORMAT ")",
195 this); 197 this, list);
196 print("before:"); 198 print("before:");
197 list->print("list:"); 199 list->print("list:");
198 } 200 }
199 if (list->is_empty()) { 201 if (list->is_empty()) {
200 // Enqueuing the empty list: nothing to do. 202 // Enqueuing the empty list: nothing to do.
209 } else { 211 } else {
210 // Prepend argument list to our queue. 212 // Prepend argument list to our queue.
211 list->remove_end()->set_older(insert_end()); 213 list->remove_end()->set_older(insert_end());
212 insert_end()->set_newer(list->remove_end()); 214 insert_end()->set_newer(list->remove_end());
213 set_insert_end(list->insert_end()); 215 set_insert_end(list->insert_end());
216 set_length(length() + list_length);
214 // empty the argument list. 217 // empty the argument list.
215 } 218 }
216 set_length(length() + list_length);
217 list->initialize(); 219 list->initialize();
218 if (TraceGCTaskQueue) { 220 if (TraceGCTaskQueue) {
219 print("after:"); 221 print("after:");
220 list->print("list:"); 222 list->print("list:");
221 } 223 }
224 verify_length();
222 } 225 }
223 226
224 // Dequeue one task. 227 // Dequeue one task.
225 GCTask* GCTaskQueue::dequeue() { 228 GCTask* GCTaskQueue::dequeue() {
226 if (TraceGCTaskQueue) { 229 if (TraceGCTaskQueue) {
286 } 289 }
287 result->set_newer(NULL); 290 result->set_newer(NULL);
288 decrement_length(); 291 decrement_length();
289 assert(result->newer() == NULL, "shouldn't be on queue"); 292 assert(result->newer() == NULL, "shouldn't be on queue");
290 assert(result->older() == NULL, "shouldn't be on queue"); 293 assert(result->older() == NULL, "shouldn't be on queue");
294 verify_length();
291 return result; 295 return result;
292 } 296 }
293 297
294 GCTask* GCTaskQueue::remove(GCTask* task) { 298 GCTask* GCTaskQueue::remove(GCTask* task) {
295 // This is slightly more work, and has slightly fewer asserts 299 // This is slightly more work, and has slightly fewer asserts
309 set_remove_end(result->newer()); 313 set_remove_end(result->newer());
310 } 314 }
311 result->set_newer(NULL); 315 result->set_newer(NULL);
312 result->set_older(NULL); 316 result->set_older(NULL);
313 decrement_length(); 317 decrement_length();
318 verify_length();
314 return result; 319 return result;
315 } 320 }
316 321
317 NOT_PRODUCT( 322 NOT_PRODUCT(
323 // Count the elements in the queue and verify the length against
324 // that count.
325 void GCTaskQueue::verify_length() const {
326 uint count = 0;
327 for (GCTask* element = insert_end();
328 element != NULL;
329 element = element->older()) {
330
331 count++;
332 }
333 assert(count == length(), "Length does not match queue");
334 }
335
318 void GCTaskQueue::print(const char* message) const { 336 void GCTaskQueue::print(const char* message) const {
319 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:" 337 tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
320 " insert_end: " INTPTR_FORMAT 338 " insert_end: " INTPTR_FORMAT
321 " remove_end: " INTPTR_FORMAT 339 " remove_end: " INTPTR_FORMAT
340 " length: %d"
322 " %s", 341 " %s",
323 this, insert_end(), remove_end(), message); 342 this, insert_end(), remove_end(), length(), message);
343 uint count = 0;
324 for (GCTask* element = insert_end(); 344 for (GCTask* element = insert_end();
325 element != NULL; 345 element != NULL;
326 element = element->older()) { 346 element = element->older()) {
327 element->print(" "); 347 element->print(" ");
348 count++;
328 tty->cr(); 349 tty->cr();
329 } 350 }
351 tty->print("Total tasks: %d", count);
330 } 352 }
331 ) 353 )
332 354
333 // 355 //
334 // SynchronizedGCTaskQueue 356 // SynchronizedGCTaskQueue
349 // 371 //
350 // GCTaskManager 372 // GCTaskManager
351 // 373 //
352 GCTaskManager::GCTaskManager(uint workers) : 374 GCTaskManager::GCTaskManager(uint workers) :
353 _workers(workers), 375 _workers(workers),
376 _active_workers(0),
377 _idle_workers(0),
354 _ndc(NULL) { 378 _ndc(NULL) {
355 initialize(); 379 initialize();
356 } 380 }
357 381
358 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) : 382 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
359 _workers(workers), 383 _workers(workers),
384 _active_workers(0),
385 _idle_workers(0),
360 _ndc(ndc) { 386 _ndc(ndc) {
361 initialize(); 387 initialize();
362 } 388 }
363 389
364 void GCTaskManager::initialize() { 390 void GCTaskManager::initialize() {
371 Mutex::_allow_vm_block_flag); // allow_vm_block 397 Mutex::_allow_vm_block_flag); // allow_vm_block
372 // The queue for the GCTaskManager must be a CHeapObj. 398 // The queue for the GCTaskManager must be a CHeapObj.
373 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); 399 GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
374 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); 400 _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
375 _noop_task = NoopGCTask::create_on_c_heap(); 401 _noop_task = NoopGCTask::create_on_c_heap();
402 _idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap();
376 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers()); 403 _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
377 { 404 {
378 // Set up worker threads. 405 // Set up worker threads.
379 // Distribute the workers among the available processors, 406 // Distribute the workers among the available processors,
380 // unless we were told not to, or if the os doesn't want to. 407 // unless we were told not to, or if the os doesn't want to.
416 GCTaskManager::~GCTaskManager() { 443 GCTaskManager::~GCTaskManager() {
417 assert(busy_workers() == 0, "still have busy workers"); 444 assert(busy_workers() == 0, "still have busy workers");
418 assert(queue()->is_empty(), "still have queued work"); 445 assert(queue()->is_empty(), "still have queued work");
419 NoopGCTask::destroy(_noop_task); 446 NoopGCTask::destroy(_noop_task);
420 _noop_task = NULL; 447 _noop_task = NULL;
448 WaitForBarrierGCTask::destroy(_idle_inactive_task);
449 _idle_inactive_task = NULL;
421 if (_thread != NULL) { 450 if (_thread != NULL) {
422 for (uint i = 0; i < workers(); i += 1) { 451 for (uint i = 0; i < workers(); i += 1) {
423 GCTaskThread::destroy(thread(i)); 452 GCTaskThread::destroy(thread(i));
424 set_thread(i, NULL); 453 set_thread(i, NULL);
425 } 454 }
440 delete monitor(); 469 delete monitor();
441 _monitor = NULL; 470 _monitor = NULL;
442 } 471 }
443 } 472 }
444 473
474 void GCTaskManager::set_active_gang() {
475 _active_workers =
476 AdaptiveSizePolicy::calc_active_workers(workers(),
477 active_workers(),
478 Threads::number_of_non_daemon_threads());
479
480 assert(!all_workers_active() || active_workers() == ParallelGCThreads,
481 err_msg("all_workers_active() is incorrect: "
482 "active %d ParallelGCThreads %d", active_workers(),
483 ParallelGCThreads));
484 if (TraceDynamicGCThreads) {
485 gclog_or_tty->print_cr("GCTaskManager::set_active_gang(): "
486 "all_workers_active() %d workers %d "
487 "active %d ParallelGCThreads %d ",
488 all_workers_active(), workers(), active_workers(),
489 ParallelGCThreads);
490 }
491 }
492
493 // Create IdleGCTasks for inactive workers.
494 // Creates tasks in a ResourceArea and assumes
495 // an appropriate ResourceMark.
496 void GCTaskManager::task_idle_workers() {
497 {
498 int more_inactive_workers = 0;
499 {
500 // Stop any idle tasks from exiting their IdleGCTask's
501 // and get the count for additional IdleGCTask's under
502 // the GCTaskManager's monitor so that the "more_inactive_workers"
503 // count is correct.
504 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
505 _idle_inactive_task->set_should_wait(true);
506 // active_workers are a number being requested. idle_workers
507 // are the number currently idle. If all the workers are being
508 // requested to be active but some are already idle, reduce
509 // the number of active_workers to be consistent with the
510 // number of idle_workers. The idle_workers are stuck in
511 // idle tasks and will no longer be release (since a new GC
512 // is starting). Try later to release enough idle_workers
513 // to allow the desired number of active_workers.
514 more_inactive_workers =
515 workers() - active_workers() - idle_workers();
516 if (more_inactive_workers < 0) {
517 int reduced_active_workers = active_workers() + more_inactive_workers;
518 set_active_workers(reduced_active_workers);
519 more_inactive_workers = 0;
520 }
521 if (TraceDynamicGCThreads) {
522 gclog_or_tty->print_cr("JT: %d workers %d active %d "
523 "idle %d more %d",
524 Threads::number_of_non_daemon_threads(),
525 workers(),
526 active_workers(),
527 idle_workers(),
528 more_inactive_workers);
529 }
530 }
531 GCTaskQueue* q = GCTaskQueue::create();
532 for(uint i = 0; i < (uint) more_inactive_workers; i++) {
533 q->enqueue(IdleGCTask::create_on_c_heap());
534 increment_idle_workers();
535 }
536 assert(workers() == active_workers() + idle_workers(),
537 "total workers should equal active + inactive");
538 add_list(q);
539 // GCTaskQueue* q was created in a ResourceArea so a
540 // destroy() call is not needed.
541 }
542 }
543
544 void GCTaskManager::release_idle_workers() {
545 {
546 MutexLockerEx ml(monitor(),
547 Mutex::_no_safepoint_check_flag);
548 _idle_inactive_task->set_should_wait(false);
549 monitor()->notify_all();
550 // Release monitor
551 }
552 }
553
445 void GCTaskManager::print_task_time_stamps() { 554 void GCTaskManager::print_task_time_stamps() {
446 for(uint i=0; i<ParallelGCThreads; i++) { 555 for(uint i=0; i<ParallelGCThreads; i++) {
447 GCTaskThread* t = thread(i); 556 GCTaskThread* t = thread(i);
448 t->print_task_time_stamps(); 557 t->print_task_time_stamps();
449 } 558 }
507 monitor()->name()); 616 monitor()->name());
508 } 617 }
509 (void) monitor()->notify_all(); 618 (void) monitor()->notify_all();
510 // Release monitor(). 619 // Release monitor().
511 } 620 }
621
622 // GC workers wait in get_task() for new work to be added
623 // to the GCTaskManager's queue. When new work is added,
624 // a notify is sent to the waiting GC workers which then
625 // compete to get tasks. If a GC worker wakes up and there
626 // is no work on the queue, it is given a noop_task to execute
627 // and then loops to find more work.
512 628
513 GCTask* GCTaskManager::get_task(uint which) { 629 GCTask* GCTaskManager::get_task(uint which) {
514 GCTask* result = NULL; 630 GCTask* result = NULL;
515 // Grab the queue lock. 631 // Grab the queue lock.
516 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); 632 MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
556 if (TraceGCTaskManager) { 672 if (TraceGCTaskManager) {
557 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]", 673 tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
558 which, result, GCTask::Kind::to_string(result->kind())); 674 which, result, GCTask::Kind::to_string(result->kind()));
559 tty->print_cr(" %s", result->name()); 675 tty->print_cr(" %s", result->name());
560 } 676 }
561 increment_busy_workers(); 677 if (!result->is_idle_task()) {
562 increment_delivered_tasks(); 678 increment_busy_workers();
679 increment_delivered_tasks();
680 }
563 return result; 681 return result;
564 // Release monitor(). 682 // Release monitor().
565 } 683 }
566 684
567 void GCTaskManager::note_completion(uint which) { 685 void GCTaskManager::note_completion(uint which) {
620 return _busy_workers; 738 return _busy_workers;
621 } 739 }
622 740
623 uint GCTaskManager::decrement_busy_workers() { 741 uint GCTaskManager::decrement_busy_workers() {
624 assert(queue()->own_lock(), "don't own the lock"); 742 assert(queue()->own_lock(), "don't own the lock");
743 assert(_busy_workers > 0, "About to make a mistake");
625 _busy_workers -= 1; 744 _busy_workers -= 1;
626 return _busy_workers; 745 return _busy_workers;
627 } 746 }
628 747
629 void GCTaskManager::release_all_resources() { 748 void GCTaskManager::release_all_resources() {
641 void GCTaskManager::note_release(uint which) { 760 void GCTaskManager::note_release(uint which) {
642 // This can be done without a lock because each thread writes one element. 761 // This can be done without a lock because each thread writes one element.
643 set_resource_flag(which, false); 762 set_resource_flag(which, false);
644 } 763 }
645 764
765 // "list" contains tasks that are ready to execute. Those
766 // tasks are added to the GCTaskManager's queue of tasks and
767 // then the GC workers are notified that there is new work to
768 // do.
769 //
770 // Typically different types of tasks can be added to the "list".
771 // For example in PSScavenge OldToYoungRootsTask, SerialOldToYoungRootsTask,
772 // ScavengeRootsTask, and StealTask tasks are all added to the list
773 // and then the GC workers are notified of new work. The tasks are
774 // handed out in the order in which they are added to the list
775 // (although execution is not necessarily in that order). As long
776 // as any tasks are running the GCTaskManager will wait for execution
777 // to complete. GC workers that execute a stealing task remain in
778 // the stealing task until all stealing tasks have completed. The load
779 // balancing afforded by the stealing tasks work best if the stealing
780 // tasks are added last to the list.
781
646 void GCTaskManager::execute_and_wait(GCTaskQueue* list) { 782 void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
647 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create(); 783 WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
648 list->enqueue(fin); 784 list->enqueue(fin);
649 add_list(list); 785 add_list(list);
650 fin->wait_for(); 786 fin->wait_for(true /* reset */);
651 // We have to release the barrier tasks! 787 // We have to release the barrier tasks!
652 WaitForBarrierGCTask::destroy(fin); 788 WaitForBarrierGCTask::destroy(fin);
653 } 789 }
654 790
655 bool GCTaskManager::resource_flag(uint which) { 791 bool GCTaskManager::resource_flag(uint which) {
684 } 820 }
685 } 821 }
686 } 822 }
687 823
688 void NoopGCTask::destruct() { 824 void NoopGCTask::destruct() {
825 // This has to know it's superclass structure, just like the constructor.
826 this->GCTask::destruct();
827 // Nothing else to do.
828 }
829
830 //
831 // IdleGCTask
832 //
833
834 IdleGCTask* IdleGCTask::create() {
835 IdleGCTask* result = new IdleGCTask(false);
836 return result;
837 }
838
839 IdleGCTask* IdleGCTask::create_on_c_heap() {
840 IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true);
841 return result;
842 }
843
844 void IdleGCTask::do_it(GCTaskManager* manager, uint which) {
845 WaitForBarrierGCTask* wait_for_task = manager->idle_inactive_task();
846 if (TraceGCTaskManager) {
847 tty->print_cr("[" INTPTR_FORMAT "]"
848 " IdleGCTask:::do_it()"
849 " should_wait: %s",
850 this, wait_for_task->should_wait() ? "true" : "false");
851 }
852 MutexLockerEx ml(manager->monitor(), Mutex::_no_safepoint_check_flag);
853 if (TraceDynamicGCThreads) {
854 gclog_or_tty->print_cr("--- idle %d", which);
855 }
856 // Increment has to be done when the idle tasks are created.
857 // manager->increment_idle_workers();
858 manager->monitor()->notify_all();
859 while (wait_for_task->should_wait()) {
860 if (TraceGCTaskManager) {
861 tty->print_cr("[" INTPTR_FORMAT "]"
862 " IdleGCTask::do_it()"
863 " [" INTPTR_FORMAT "] (%s)->wait()",
864 this, manager->monitor(), manager->monitor()->name());
865 }
866 manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
867 }
868 manager->decrement_idle_workers();
869 if (TraceDynamicGCThreads) {
870 gclog_or_tty->print_cr("--- release %d", which);
871 }
872 if (TraceGCTaskManager) {
873 tty->print_cr("[" INTPTR_FORMAT "]"
874 " IdleGCTask::do_it() returns"
875 " should_wait: %s",
876 this, wait_for_task->should_wait() ? "true" : "false");
877 }
878 // Release monitor().
879 }
880
881 void IdleGCTask::destroy(IdleGCTask* that) {
882 if (that != NULL) {
883 that->destruct();
884 if (that->is_c_heap_obj()) {
885 FreeHeap(that);
886 }
887 }
888 }
889
890 void IdleGCTask::destruct() {
689 // This has to know it's superclass structure, just like the constructor. 891 // This has to know it's superclass structure, just like the constructor.
690 this->GCTask::destruct(); 892 this->GCTask::destruct();
691 // Nothing else to do. 893 // Nothing else to do.
692 } 894 }
693 895
766 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false); 968 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
767 return result; 969 return result;
768 } 970 }
769 971
770 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() { 972 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
771 WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true); 973 WaitForBarrierGCTask* result =
974 new (ResourceObj::C_HEAP) WaitForBarrierGCTask(true);
772 return result; 975 return result;
773 } 976 }
774 977
775 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) : 978 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
776 _is_c_heap_obj(on_c_heap) { 979 _is_c_heap_obj(on_c_heap) {
847 monitor()->notify_all(); 1050 monitor()->notify_all();
848 // Release monitor(). 1051 // Release monitor().
849 } 1052 }
850 } 1053 }
851 1054
852 void WaitForBarrierGCTask::wait_for() { 1055 void WaitForBarrierGCTask::wait_for(bool reset) {
853 if (TraceGCTaskManager) { 1056 if (TraceGCTaskManager) {
854 tty->print_cr("[" INTPTR_FORMAT "]" 1057 tty->print_cr("[" INTPTR_FORMAT "]"
855 " WaitForBarrierGCTask::wait_for()" 1058 " WaitForBarrierGCTask::wait_for()"
856 " should_wait: %s", 1059 " should_wait: %s",
857 this, should_wait() ? "true" : "false"); 1060 this, should_wait() ? "true" : "false");
867 this, monitor(), monitor()->name()); 1070 this, monitor(), monitor()->name());
868 } 1071 }
869 monitor()->wait(Mutex::_no_safepoint_check_flag, 0); 1072 monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
870 } 1073 }
871 // Reset the flag in case someone reuses this task. 1074 // Reset the flag in case someone reuses this task.
872 set_should_wait(true); 1075 if (reset) {
1076 set_should_wait(true);
1077 }
873 if (TraceGCTaskManager) { 1078 if (TraceGCTaskManager) {
874 tty->print_cr("[" INTPTR_FORMAT "]" 1079 tty->print_cr("[" INTPTR_FORMAT "]"
875 " WaitForBarrierGCTask::wait_for() returns" 1080 " WaitForBarrierGCTask::wait_for() returns"
876 " should_wait: %s", 1081 " should_wait: %s",
877 this, should_wait() ? "true" : "false"); 1082 this, should_wait() ? "true" : "false");