comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 1709:5f429ee79634

6966222: G1: simplify TaskQueue overflow handling Reviewed-by: tonyp, ysr
author jcoomes
date Mon, 09 Aug 2010 05:41:05 -0700
parents 0ce1569c90e5
children 688c3755d7af
comparison
equal deleted inserted replaced
1708:a03ae377b2e8 1709:5f429ee79634
2708 r->rem_set()->set_iter_claimed(0); 2708 r->rem_set()->set_iter_claimed(0);
2709 return false; 2709 return false;
2710 } 2710 }
2711 }; 2711 };
2712 2712
2713 #if TASKQUEUE_STATS
2714 void G1CollectedHeap::print_taskqueue_stats_hdr(outputStream* const st) {
2715 st->print_raw_cr("GC Task Stats");
2716 st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
2717 st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
2718 }
2719
2720 void G1CollectedHeap::print_taskqueue_stats(outputStream* const st) const {
2721 print_taskqueue_stats_hdr(st);
2722
2723 TaskQueueStats totals;
2724 const int n = MAX2(workers()->total_workers(), 1);
2725 for (int i = 0; i < n; ++i) {
2726 st->print("%3d ", i); task_queue(i)->stats.print(st); st->cr();
2727 totals += task_queue(i)->stats;
2728 }
2729 st->print_raw("tot "); totals.print(st); st->cr();
2730
2731 DEBUG_ONLY(totals.verify());
2732 }
2733
2734 void G1CollectedHeap::reset_taskqueue_stats() {
2735 const int n = MAX2(workers()->total_workers(), 1);
2736 for (int i = 0; i < n; ++i) {
2737 task_queue(i)->stats.reset();
2738 }
2739 }
2740 #endif // TASKQUEUE_STATS
2741
2713 void 2742 void
2714 G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { 2743 G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
2715 if (GC_locker::check_active_before_gc()) { 2744 if (GC_locker::check_active_before_gc()) {
2716 return; // GC is disabled (e.g. JNI GetXXXCritical operation) 2745 return; // GC is disabled (e.g. JNI GetXXXCritical operation)
2717 } 2746 }
2967 gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum); 2996 gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
2968 print_tracing_info(); 2997 print_tracing_info();
2969 vm_exit(-1); 2998 vm_exit(-1);
2970 } 2999 }
2971 } 3000 }
3001
3002 TASKQUEUE_STATS_ONLY(if (ParallelGCVerbose) print_taskqueue_stats());
3003 TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
2972 3004
2973 if (PrintHeapAtGC) { 3005 if (PrintHeapAtGC) {
2974 Universe::print_heap_after_gc(); 3006 Universe::print_heap_after_gc();
2975 } 3007 }
2976 if (G1SummarizeRSetStats && 3008 if (G1SummarizeRSetStats &&
3713 _hash_seed(17), _queue_num(queue_num), 3745 _hash_seed(17), _queue_num(queue_num),
3714 _term_attempts(0), 3746 _term_attempts(0),
3715 _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)), 3747 _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)),
3716 _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)), 3748 _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)),
3717 _age_table(false), 3749 _age_table(false),
3718 #if G1_DETAILED_STATS
3719 _pushes(0), _pops(0), _steals(0),
3720 _steal_attempts(0), _overflow_pushes(0),
3721 #endif
3722 _strong_roots_time(0), _term_time(0), 3750 _strong_roots_time(0), _term_time(0),
3723 _alloc_buffer_waste(0), _undo_waste(0) 3751 _alloc_buffer_waste(0), _undo_waste(0)
3724 { 3752 {
3725 // we allocate G1YoungSurvRateNumRegions plus one entries, since 3753 // we allocate G1YoungSurvRateNumRegions plus one entries, since
3726 // we "sacrifice" entry 0 to keep track of surviving bytes for 3754 // we "sacrifice" entry 0 to keep track of surviving bytes for
3736 vm_exit_out_of_memory(array_length * sizeof(size_t), 3764 vm_exit_out_of_memory(array_length * sizeof(size_t),
3737 "Not enough space for young surv histo."); 3765 "Not enough space for young surv histo.");
3738 _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; 3766 _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
3739 memset(_surviving_young_words, 0, real_length * sizeof(size_t)); 3767 memset(_surviving_young_words, 0, real_length * sizeof(size_t));
3740 3768
3741 _overflowed_refs = new OverflowQueue(10);
3742
3743 _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer; 3769 _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
3744 _alloc_buffers[GCAllocForTenured] = &_tenured_alloc_buffer; 3770 _alloc_buffers[GCAllocForTenured] = &_tenured_alloc_buffer;
3745 3771
3746 _start = os::elapsedTime(); 3772 _start = os::elapsedTime();
3773 }
3774
3775 void
3776 G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
3777 {
3778 st->print_raw_cr("GC Termination Stats");
3779 st->print_raw_cr(" elapsed --strong roots-- -------termination-------"
3780 " ------waste (KiB)------");
3781 st->print_raw_cr("thr ms ms % ms % attempts"
3782 " total alloc undo");
3783 st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
3784 " ------- ------- -------");
3785 }
3786
3787 void
3788 G1ParScanThreadState::print_termination_stats(int i,
3789 outputStream* const st) const
3790 {
3791 const double elapsed_ms = elapsed_time() * 1000.0;
3792 const double s_roots_ms = strong_roots_time() * 1000.0;
3793 const double term_ms = term_time() * 1000.0;
3794 st->print_cr("%3d %9.2f %9.2f %6.2f "
3795 "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
3796 SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
3797 i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
3798 term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
3799 (alloc_buffer_waste() + undo_waste()) * HeapWordSize / K,
3800 alloc_buffer_waste() * HeapWordSize / K,
3801 undo_waste() * HeapWordSize / K);
3747 } 3802 }
3748 3803
3749 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 3804 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
3750 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), 3805 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
3751 _par_scan_state(par_scan_state) { } 3806 _par_scan_state(par_scan_state) { }
3950 4005
3951 void do_void() { 4006 void do_void() {
3952 G1ParScanThreadState* pss = par_scan_state(); 4007 G1ParScanThreadState* pss = par_scan_state();
3953 while (true) { 4008 while (true) {
3954 pss->trim_queue(); 4009 pss->trim_queue();
3955 IF_G1_DETAILED_STATS(pss->note_steal_attempt());
3956 4010
3957 StarTask stolen_task; 4011 StarTask stolen_task;
3958 if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) { 4012 if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
3959 IF_G1_DETAILED_STATS(pss->note_steal());
3960
3961 // slightly paranoid tests; I'm trying to catch potential 4013 // slightly paranoid tests; I'm trying to catch potential
3962 // problems before we go into push_on_queue to know where the 4014 // problems before we go into push_on_queue to know where the
3963 // problem is coming from 4015 // problem is coming from
3964 assert((oop*)stolen_task != NULL, "Error"); 4016 assert((oop*)stolen_task != NULL, "Error");
3965 if (stolen_task.is_narrow()) { 4017 if (stolen_task.is_narrow()) {
4074 _g1h->update_surviving_young_words(pss.surviving_young_words()+1); 4126 _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
4075 4127
4076 // Clean up any par-expanded rem sets. 4128 // Clean up any par-expanded rem sets.
4077 HeapRegionRemSet::par_cleanup(); 4129 HeapRegionRemSet::par_cleanup();
4078 4130
4079 MutexLocker x(stats_lock());
4080 if (ParallelGCVerbose) { 4131 if (ParallelGCVerbose) {
4081 gclog_or_tty->print("Thread %d complete:\n", i); 4132 MutexLocker x(stats_lock());
4082 #if G1_DETAILED_STATS 4133 pss.print_termination_stats(i);
4083 gclog_or_tty->print(" Pushes: %7d Pops: %7d Overflows: %7d Steals %7d (in %d attempts)\n",
4084 pss.pushes(),
4085 pss.pops(),
4086 pss.overflow_pushes(),
4087 pss.steals(),
4088 pss.steal_attempts());
4089 #endif
4090 double elapsed = pss.elapsed();
4091 double strong_roots = pss.strong_roots_time();
4092 double term = pss.term_time();
4093 gclog_or_tty->print(" Elapsed: %7.2f ms.\n"
4094 " Strong roots: %7.2f ms (%6.2f%%)\n"
4095 " Termination: %7.2f ms (%6.2f%%) "
4096 "(in "SIZE_FORMAT" entries)\n",
4097 elapsed * 1000.0,
4098 strong_roots * 1000.0, (strong_roots*100.0/elapsed),
4099 term * 1000.0, (term*100.0/elapsed),
4100 pss.term_attempts());
4101 size_t total_waste = pss.alloc_buffer_waste() + pss.undo_waste();
4102 gclog_or_tty->print(" Waste: %8dK\n"
4103 " Alloc Buffer: %8dK\n"
4104 " Undo: %8dK\n",
4105 (total_waste * HeapWordSize) / K,
4106 (pss.alloc_buffer_waste() * HeapWordSize) / K,
4107 (pss.undo_waste() * HeapWordSize) / K);
4108 } 4134 }
4109 4135
4110 assert(pss.refs_to_scan() == 0, "Task queue should be empty"); 4136 assert(pss.refs_to_scan() == 0, "Task queue should be empty");
4111 assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty"); 4137 assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
4112 double end_time_ms = os::elapsedTime() * 1000.0; 4138 double end_time_ms = os::elapsedTime() * 1000.0;
4219 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); 4245 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
4220 double start_par = os::elapsedTime(); 4246 double start_par = os::elapsedTime();
4221 if (ParallelGCThreads > 0) { 4247 if (ParallelGCThreads > 0) {
4222 // The individual threads will set their evac-failure closures. 4248 // The individual threads will set their evac-failure closures.
4223 StrongRootsScope srs(this); 4249 StrongRootsScope srs(this);
4250 if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
4224 workers()->run_task(&g1_par_task); 4251 workers()->run_task(&g1_par_task);
4225 } else { 4252 } else {
4226 StrongRootsScope srs(this); 4253 StrongRootsScope srs(this);
4227 g1_par_task.work(0); 4254 g1_par_task.work(0);
4228 } 4255 }