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