Mercurial > hg > graal-jvmci-8
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 } |