comparison src/share/vm/gc_implementation/parNew/parNewGeneration.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 92da084fefc9
children 441e946dc1af
comparison
equal deleted inserted replaced
4094:3a298e04d914 4095:bca17e38de00
303 303
304 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); } 304 ~ParScanThreadStateSet() { TASKQUEUE_STATS_ONLY(reset_stats()); }
305 305
306 inline ParScanThreadState& thread_state(int i); 306 inline ParScanThreadState& thread_state(int i);
307 307
308 void reset(bool promotion_failed); 308 void reset(int active_workers, bool promotion_failed);
309 void flush(); 309 void flush();
310 310
311 #if TASKQUEUE_STATS 311 #if TASKQUEUE_STATS
312 static void 312 static void
313 print_termination_stats_hdr(outputStream* const st = gclog_or_tty); 313 print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
320 320
321 private: 321 private:
322 ParallelTaskTerminator& _term; 322 ParallelTaskTerminator& _term;
323 ParNewGeneration& _gen; 323 ParNewGeneration& _gen;
324 Generation& _next_gen; 324 Generation& _next_gen;
325 public:
326 bool is_valid(int id) const { return id < length(); }
327 ParallelTaskTerminator* terminator() { return &_term; }
325 }; 328 };
326 329
327 330
328 ParScanThreadStateSet::ParScanThreadStateSet( 331 ParScanThreadStateSet::ParScanThreadStateSet(
329 int num_threads, Space& to_space, ParNewGeneration& gen, 332 int num_threads, Space& to_space, ParNewGeneration& gen,
349 assert(i >= 0 && i < length(), "sanity check!"); 352 assert(i >= 0 && i < length(), "sanity check!");
350 return ((ParScanThreadState*)_data)[i]; 353 return ((ParScanThreadState*)_data)[i];
351 } 354 }
352 355
353 356
354 void ParScanThreadStateSet::reset(bool promotion_failed) 357 void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
355 { 358 {
356 _term.reset_for_reuse(); 359 _term.reset_for_reuse(active_threads);
357 if (promotion_failed) { 360 if (promotion_failed) {
358 for (int i = 0; i < length(); ++i) { 361 for (int i = 0; i < length(); ++i) {
359 thread_state(i).print_and_clear_promotion_failure_size(); 362 thread_state(i).print_and_clear_promotion_failure_size();
360 } 363 }
361 } 364 }
567 _gen(gen), _next_gen(next_gen), 570 _gen(gen), _next_gen(next_gen),
568 _young_old_boundary(young_old_boundary), 571 _young_old_boundary(young_old_boundary),
569 _state_set(state_set) 572 _state_set(state_set)
570 {} 573 {}
571 574
575 // Reset the terminator for the given number of
576 // active threads.
577 void ParNewGenTask::set_for_termination(int active_workers) {
578 _state_set->reset(active_workers, _gen->promotion_failed());
579 // Should the heap be passed in? There's only 1 for now so
580 // grab it instead.
581 GenCollectedHeap* gch = GenCollectedHeap::heap();
582 gch->set_n_termination(active_workers);
583 }
584
585 // The "i" passed to this method is the part of the work for
586 // this thread. It is not the worker ID. The "i" is derived
587 // from _started_workers which is incremented in internal_note_start()
588 // called in GangWorker loop() and which is called under the
589 // which is called under the protection of the gang monitor and is
590 // called after a task is started. So "i" is based on
591 // first-come-first-served.
592
572 void ParNewGenTask::work(int i) { 593 void ParNewGenTask::work(int i) {
573 GenCollectedHeap* gch = GenCollectedHeap::heap(); 594 GenCollectedHeap* gch = GenCollectedHeap::heap();
574 // Since this is being done in a separate thread, need new resource 595 // Since this is being done in a separate thread, need new resource
575 // and handle marks. 596 // and handle marks.
576 ResourceMark rm; 597 ResourceMark rm;
579 assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen."); 600 assert(gch->n_gens() == 2, "Par young collection currently only works with one older gen.");
580 601
581 Generation* old_gen = gch->next_gen(_gen); 602 Generation* old_gen = gch->next_gen(_gen);
582 603
583 ParScanThreadState& par_scan_state = _state_set->thread_state(i); 604 ParScanThreadState& par_scan_state = _state_set->thread_state(i);
605 assert(_state_set->is_valid(i), "Should not have been called");
606
584 par_scan_state.set_young_old_boundary(_young_old_boundary); 607 par_scan_state.set_young_old_boundary(_young_old_boundary);
585 608
586 par_scan_state.start_strong_roots(); 609 par_scan_state.start_strong_roots();
587 gch->gen_process_strong_roots(_gen->level(), 610 gch->gen_process_strong_roots(_gen->level(),
588 true, // Process younger gens, if any, 611 true, // Process younger gens, if any,
731 HeapWord* young_old_boundary, 754 HeapWord* young_old_boundary,
732 ParScanThreadStateSet& state_set); 755 ParScanThreadStateSet& state_set);
733 756
734 private: 757 private:
735 virtual void work(int i); 758 virtual void work(int i);
736 759 virtual void set_for_termination(int active_workers) {
760 _state_set.terminator()->reset_for_reuse(active_workers);
761 }
737 private: 762 private:
738 ParNewGeneration& _gen; 763 ParNewGeneration& _gen;
739 ProcessTask& _task; 764 ProcessTask& _task;
740 Generation& _next_gen; 765 Generation& _next_gen;
741 HeapWord* _young_old_boundary; 766 HeapWord* _young_old_boundary;
787 void ParNewRefProcTaskExecutor::execute(ProcessTask& task) 812 void ParNewRefProcTaskExecutor::execute(ProcessTask& task)
788 { 813 {
789 GenCollectedHeap* gch = GenCollectedHeap::heap(); 814 GenCollectedHeap* gch = GenCollectedHeap::heap();
790 assert(gch->kind() == CollectedHeap::GenCollectedHeap, 815 assert(gch->kind() == CollectedHeap::GenCollectedHeap,
791 "not a generational heap"); 816 "not a generational heap");
792 WorkGang* workers = gch->workers(); 817 FlexibleWorkGang* workers = gch->workers();
793 assert(workers != NULL, "Need parallel worker threads."); 818 assert(workers != NULL, "Need parallel worker threads.");
819 _state_set.reset(workers->active_workers(), _generation.promotion_failed());
794 ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(), 820 ParNewRefProcTaskProxy rp_task(task, _generation, *_generation.next_gen(),
795 _generation.reserved().end(), _state_set); 821 _generation.reserved().end(), _state_set);
796 workers->run_task(&rp_task); 822 workers->run_task(&rp_task);
797 _state_set.reset(_generation.promotion_failed()); 823 _state_set.reset(0 /* bad value in debug if not reset */,
824 _generation.promotion_failed());
798 } 825 }
799 826
800 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) 827 void ParNewRefProcTaskExecutor::execute(EnqueueTask& task)
801 { 828 {
802 GenCollectedHeap* gch = GenCollectedHeap::heap(); 829 GenCollectedHeap* gch = GenCollectedHeap::heap();
803 WorkGang* workers = gch->workers(); 830 FlexibleWorkGang* workers = gch->workers();
804 assert(workers != NULL, "Need parallel worker threads."); 831 assert(workers != NULL, "Need parallel worker threads.");
805 ParNewRefEnqueueTaskProxy enq_task(task); 832 ParNewRefEnqueueTaskProxy enq_task(task);
806 workers->run_task(&enq_task); 833 workers->run_task(&enq_task);
807 } 834 }
808 835
854 assert(full || size > 0, "otherwise we don't want to collect"); 881 assert(full || size > 0, "otherwise we don't want to collect");
855 GenCollectedHeap* gch = GenCollectedHeap::heap(); 882 GenCollectedHeap* gch = GenCollectedHeap::heap();
856 assert(gch->kind() == CollectedHeap::GenCollectedHeap, 883 assert(gch->kind() == CollectedHeap::GenCollectedHeap,
857 "not a CMS generational heap"); 884 "not a CMS generational heap");
858 AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy(); 885 AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
859 WorkGang* workers = gch->workers(); 886 FlexibleWorkGang* workers = gch->workers();
887 assert(workers != NULL, "Need workgang for parallel work");
888 int active_workers =
889 AdaptiveSizePolicy::calc_active_workers(workers->total_workers(),
890 workers->active_workers(),
891 Threads::number_of_non_daemon_threads());
892 workers->set_active_workers(active_workers);
860 _next_gen = gch->next_gen(this); 893 _next_gen = gch->next_gen(this);
861 assert(_next_gen != NULL, 894 assert(_next_gen != NULL,
862 "This must be the youngest gen, and not the only gen"); 895 "This must be the youngest gen, and not the only gen");
863 assert(gch->n_gens() == 2, 896 assert(gch->n_gens() == 2,
864 "Par collection currently only works with single older gen."); 897 "Par collection currently only works with single older gen.");
892 age_table()->clear(); 925 age_table()->clear();
893 to()->clear(SpaceDecorator::Mangle); 926 to()->clear(SpaceDecorator::Mangle);
894 927
895 gch->save_marks(); 928 gch->save_marks();
896 assert(workers != NULL, "Need parallel worker threads."); 929 assert(workers != NULL, "Need parallel worker threads.");
897 ParallelTaskTerminator _term(workers->total_workers(), task_queues()); 930 int n_workers = active_workers;
898 ParScanThreadStateSet thread_state_set(workers->total_workers(), 931
932 // Set the correct parallelism (number of queues) in the reference processor
933 ref_processor()->set_active_mt_degree(n_workers);
934
935 // Always set the terminator for the active number of workers
936 // because only those workers go through the termination protocol.
937 ParallelTaskTerminator _term(n_workers, task_queues());
938 ParScanThreadStateSet thread_state_set(workers->active_workers(),
899 *to(), *this, *_next_gen, *task_queues(), 939 *to(), *this, *_next_gen, *task_queues(),
900 _overflow_stacks, desired_plab_sz(), _term); 940 _overflow_stacks, desired_plab_sz(), _term);
901 941
902 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set); 942 ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
903 int n_workers = workers->total_workers();
904 gch->set_par_threads(n_workers); 943 gch->set_par_threads(n_workers);
905 gch->rem_set()->prepare_for_younger_refs_iterate(true); 944 gch->rem_set()->prepare_for_younger_refs_iterate(true);
906 // It turns out that even when we're using 1 thread, doing the work in a 945 // It turns out that even when we're using 1 thread, doing the work in a
907 // separate thread causes wide variance in run times. We can't help this 946 // separate thread causes wide variance in run times. We can't help this
908 // in the multi-threaded case, but we special-case n=1 here to get 947 // in the multi-threaded case, but we special-case n=1 here to get
912 workers->run_task(&tsk); 951 workers->run_task(&tsk);
913 } else { 952 } else {
914 GenCollectedHeap::StrongRootsScope srs(gch); 953 GenCollectedHeap::StrongRootsScope srs(gch);
915 tsk.work(0); 954 tsk.work(0);
916 } 955 }
917 thread_state_set.reset(promotion_failed()); 956 thread_state_set.reset(0 /* Bad value in debug if not reset */,
957 promotion_failed());
918 958
919 // Process (weak) reference objects found during scavenge. 959 // Process (weak) reference objects found during scavenge.
920 ReferenceProcessor* rp = ref_processor(); 960 ReferenceProcessor* rp = ref_processor();
921 IsAliveClosure is_alive(this); 961 IsAliveClosure is_alive(this);
922 ScanWeakRefClosure scan_weak_ref(this); 962 ScanWeakRefClosure scan_weak_ref(this);
925 ScanClosureWithParBarrier scan_with_gc_barrier(this, true); 965 ScanClosureWithParBarrier scan_with_gc_barrier(this, true);
926 set_promo_failure_scan_stack_closure(&scan_without_gc_barrier); 966 set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
927 EvacuateFollowersClosureGeneral evacuate_followers(gch, _level, 967 EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
928 &scan_without_gc_barrier, &scan_with_gc_barrier); 968 &scan_without_gc_barrier, &scan_with_gc_barrier);
929 rp->setup_policy(clear_all_soft_refs); 969 rp->setup_policy(clear_all_soft_refs);
970 // Can the mt_degree be set later (at run_task() time would be best)?
971 rp->set_active_mt_degree(active_workers);
930 if (rp->processing_is_mt()) { 972 if (rp->processing_is_mt()) {
931 ParNewRefProcTaskExecutor task_executor(*this, thread_state_set); 973 ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
932 rp->process_discovered_references(&is_alive, &keep_alive, 974 rp->process_discovered_references(&is_alive, &keep_alive,
933 &evacuate_followers, &task_executor); 975 &evacuate_followers, &task_executor);
934 } else { 976 } else {