Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 20216:570cb6369f17
8019342: G1: High "Other" time most likely due to card redirtying
Summary: Parallelize card redirtying to decrease the time it takes.
Reviewed-by: brutisso
author | tschatzl |
---|---|
date | Mon, 21 Jul 2014 09:40:19 +0200 |
parents | 983092f35ff7 |
children | 6b52700a896b |
comparison
equal
deleted
inserted
replaced
20215:983092f35ff7 | 20216:570cb6369f17 |
---|---|
96 // | 96 // |
97 | 97 |
98 // Local to this file. | 98 // Local to this file. |
99 | 99 |
100 class RefineCardTableEntryClosure: public CardTableEntryClosure { | 100 class RefineCardTableEntryClosure: public CardTableEntryClosure { |
101 G1RemSet* _g1rs; | |
102 ConcurrentG1Refine* _cg1r; | |
103 bool _concurrent; | 101 bool _concurrent; |
104 public: | 102 public: |
105 RefineCardTableEntryClosure(G1RemSet* g1rs, | 103 RefineCardTableEntryClosure() : _concurrent(true) { } |
106 ConcurrentG1Refine* cg1r) : | 104 |
107 _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) | |
108 {} | |
109 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { | 105 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
110 bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); | 106 bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false); |
111 // This path is executed by the concurrent refine or mutator threads, | 107 // This path is executed by the concurrent refine or mutator threads, |
112 // concurrently, and so we do not care if card_ptr contains references | 108 // concurrently, and so we do not care if card_ptr contains references |
113 // that point into the collection set. | 109 // that point into the collection set. |
114 assert(!oops_into_cset, "should be"); | 110 assert(!oops_into_cset, "should be"); |
115 | 111 |
118 return false; | 114 return false; |
119 } | 115 } |
120 // Otherwise, we finished successfully; return true. | 116 // Otherwise, we finished successfully; return true. |
121 return true; | 117 return true; |
122 } | 118 } |
119 | |
123 void set_concurrent(bool b) { _concurrent = b; } | 120 void set_concurrent(bool b) { _concurrent = b; } |
124 }; | 121 }; |
125 | 122 |
126 | 123 |
127 class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure { | 124 class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure { |
473 ct_bs->mod_card_iterate(&count1); | 470 ct_bs->mod_card_iterate(&count1); |
474 int orig_count = count1.n(); | 471 int orig_count = count1.n(); |
475 | 472 |
476 // First clear the logged cards. | 473 // First clear the logged cards. |
477 ClearLoggedCardTableEntryClosure clear; | 474 ClearLoggedCardTableEntryClosure clear; |
478 dcqs.set_closure(&clear); | 475 dcqs.apply_closure_to_all_completed_buffers(&clear); |
479 dcqs.apply_closure_to_all_completed_buffers(); | 476 dcqs.iterate_closure_all_threads(&clear, false); |
480 dcqs.iterate_closure_all_threads(false); | |
481 clear.print_histo(); | 477 clear.print_histo(); |
482 | 478 |
483 // Now ensure that there's no dirty cards. | 479 // Now ensure that there's no dirty cards. |
484 CountNonCleanMemRegionClosure count2(this); | 480 CountNonCleanMemRegionClosure count2(this); |
485 ct_bs->mod_card_iterate(&count2); | 481 ct_bs->mod_card_iterate(&count2); |
488 count2.n(), orig_count); | 484 count2.n(), orig_count); |
489 } | 485 } |
490 guarantee(count2.n() == 0, "Card table should be clean."); | 486 guarantee(count2.n() == 0, "Card table should be clean."); |
491 | 487 |
492 RedirtyLoggedCardTableEntryClosure redirty; | 488 RedirtyLoggedCardTableEntryClosure redirty; |
493 JavaThread::dirty_card_queue_set().set_closure(&redirty); | 489 dcqs.apply_closure_to_all_completed_buffers(&redirty); |
494 dcqs.apply_closure_to_all_completed_buffers(); | 490 dcqs.iterate_closure_all_threads(&redirty, false); |
495 dcqs.iterate_closure_all_threads(false); | |
496 gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", | 491 gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.", |
497 clear.calls(), orig_count); | 492 clear.calls(), orig_count); |
498 guarantee(redirty.calls() == clear.calls(), | 493 guarantee(redirty.calls() == clear.calls(), |
499 "Or else mechanism is broken."); | 494 "Or else mechanism is broken."); |
500 | 495 |
503 if (count3.n() != orig_count) { | 498 if (count3.n() != orig_count) { |
504 gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.", | 499 gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.", |
505 orig_count, count3.n()); | 500 orig_count, count3.n()); |
506 guarantee(count3.n() >= orig_count, "Should have restored them all."); | 501 guarantee(count3.n() >= orig_count, "Should have restored them all."); |
507 } | 502 } |
508 | |
509 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); | |
510 } | 503 } |
511 | 504 |
512 // Private class members. | 505 // Private class members. |
513 | 506 |
514 G1CollectedHeap* G1CollectedHeap::_g1h; | 507 G1CollectedHeap* G1CollectedHeap::_g1h; |
1998 // Ensure that the sizes are properly aligned. | 1991 // Ensure that the sizes are properly aligned. |
1999 Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); | 1992 Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
2000 Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); | 1993 Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap"); |
2001 Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap"); | 1994 Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap"); |
2002 | 1995 |
2003 _cg1r = new ConcurrentG1Refine(this); | 1996 _refine_cte_cl = new RefineCardTableEntryClosure(); |
1997 | |
1998 _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl); | |
2004 | 1999 |
2005 // Reserve the maximum. | 2000 // Reserve the maximum. |
2006 | 2001 |
2007 // When compressed oops are enabled, the preferred heap base | 2002 // When compressed oops are enabled, the preferred heap base |
2008 // is calculated by subtracting the requested size from the | 2003 // is calculated by subtracting the requested size from the |
2093 } | 2088 } |
2094 | 2089 |
2095 // Perform any initialization actions delegated to the policy. | 2090 // Perform any initialization actions delegated to the policy. |
2096 g1_policy()->init(); | 2091 g1_policy()->init(); |
2097 | 2092 |
2098 _refine_cte_cl = | |
2099 new RefineCardTableEntryClosure(g1_rem_set(), | |
2100 concurrent_g1_refine()); | |
2101 JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); | |
2102 | |
2103 JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, | 2093 JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon, |
2104 SATB_Q_FL_lock, | 2094 SATB_Q_FL_lock, |
2105 G1SATBProcessCompletedThreshold, | 2095 G1SATBProcessCompletedThreshold, |
2106 Shared_SATB_Q_lock); | 2096 Shared_SATB_Q_lock); |
2107 | 2097 |
2108 JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, | 2098 JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, |
2099 DirtyCardQ_CBL_mon, | |
2109 DirtyCardQ_FL_lock, | 2100 DirtyCardQ_FL_lock, |
2110 concurrent_g1_refine()->yellow_zone(), | 2101 concurrent_g1_refine()->yellow_zone(), |
2111 concurrent_g1_refine()->red_zone(), | 2102 concurrent_g1_refine()->red_zone(), |
2112 Shared_DirtyCardQ_lock); | 2103 Shared_DirtyCardQ_lock); |
2113 | 2104 |
2114 if (G1DeferredRSUpdate) { | 2105 if (G1DeferredRSUpdate) { |
2115 dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, | 2106 dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code |
2107 DirtyCardQ_CBL_mon, | |
2116 DirtyCardQ_FL_lock, | 2108 DirtyCardQ_FL_lock, |
2117 -1, // never trigger processing | 2109 -1, // never trigger processing |
2118 -1, // no limit on length | 2110 -1, // no limit on length |
2119 Shared_DirtyCardQ_lock, | 2111 Shared_DirtyCardQ_lock, |
2120 &JavaThread::dirty_card_queue_set()); | 2112 &JavaThread::dirty_card_queue_set()); |
2121 } | 2113 } |
2122 | 2114 |
2123 // Initialize the card queue set used to hold cards containing | 2115 // Initialize the card queue set used to hold cards containing |
2124 // references into the collection set. | 2116 // references into the collection set. |
2125 _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon, | 2117 _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code |
2118 DirtyCardQ_CBL_mon, | |
2126 DirtyCardQ_FL_lock, | 2119 DirtyCardQ_FL_lock, |
2127 -1, // never trigger processing | 2120 -1, // never trigger processing |
2128 -1, // no limit on length | 2121 -1, // no limit on length |
2129 Shared_DirtyCardQ_lock, | 2122 Shared_DirtyCardQ_lock, |
2130 &JavaThread::dirty_card_queue_set()); | 2123 &JavaThread::dirty_card_queue_set()); |
5282 G1StringDedup::unlink(is_alive); | 5275 G1StringDedup::unlink(is_alive); |
5283 } | 5276 } |
5284 } | 5277 } |
5285 | 5278 |
5286 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { | 5279 class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { |
5287 public: | 5280 private: |
5281 size_t _num_processed; | |
5282 | |
5283 public: | |
5284 RedirtyLoggedCardTableEntryFastClosure() : CardTableEntryClosure(), _num_processed(0) { } | |
5285 | |
5288 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { | 5286 bool do_card_ptr(jbyte* card_ptr, uint worker_i) { |
5289 *card_ptr = CardTableModRefBS::dirty_card_val(); | 5287 *card_ptr = CardTableModRefBS::dirty_card_val(); |
5288 _num_processed++; | |
5290 return true; | 5289 return true; |
5290 } | |
5291 | |
5292 size_t num_processed() const { return _num_processed; } | |
5293 }; | |
5294 | |
5295 class G1RedirtyLoggedCardsTask : public AbstractGangTask { | |
5296 private: | |
5297 DirtyCardQueueSet* _queue; | |
5298 public: | |
5299 G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { } | |
5300 | |
5301 virtual void work(uint worker_id) { | |
5302 double start_time = os::elapsedTime(); | |
5303 | |
5304 RedirtyLoggedCardTableEntryFastClosure cl; | |
5305 if (G1CollectedHeap::heap()->use_parallel_gc_threads()) { | |
5306 _queue->par_apply_closure_to_all_completed_buffers(&cl); | |
5307 } else { | |
5308 _queue->apply_closure_to_all_completed_buffers(&cl); | |
5309 } | |
5310 | |
5311 G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times(); | |
5312 timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0); | |
5313 timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed()); | |
5291 } | 5314 } |
5292 }; | 5315 }; |
5293 | 5316 |
5294 void G1CollectedHeap::redirty_logged_cards() { | 5317 void G1CollectedHeap::redirty_logged_cards() { |
5295 guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates."); | 5318 guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates."); |
5296 double redirty_logged_cards_start = os::elapsedTime(); | 5319 double redirty_logged_cards_start = os::elapsedTime(); |
5297 | 5320 |
5298 RedirtyLoggedCardTableEntryFastClosure redirty; | 5321 uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? |
5299 dirty_card_queue_set().set_closure(&redirty); | 5322 _g1h->workers()->active_workers() : 1); |
5300 dirty_card_queue_set().apply_closure_to_all_completed_buffers(); | 5323 |
5324 G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set()); | |
5325 dirty_card_queue_set().reset_for_par_iteration(); | |
5326 if (use_parallel_gc_threads()) { | |
5327 set_par_threads(n_workers); | |
5328 workers()->run_task(&redirty_task); | |
5329 set_par_threads(0); | |
5330 } else { | |
5331 redirty_task.work(0); | |
5332 } | |
5301 | 5333 |
5302 DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); | 5334 DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set(); |
5303 dcq.merge_bufferlists(&dirty_card_queue_set()); | 5335 dcq.merge_bufferlists(&dirty_card_queue_set()); |
5304 assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); | 5336 assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); |
5305 | 5337 |