src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
Print this page
rev 6279 : imported patch fast-cset-uses-biasedarray
rev 6282 : 8028710: G1 does not retire allocation buffers after reference processing work
Summary: G1 does not retire allocation buffers after reference processing work when -XX:+ParallelRefProcEnabled is enabled.
Reviewed-by:
rev 6283 : 8019342: G1: High "Other" time most likely due to card redirtying
Summary: Parallelize card redirtying to decrease the time it takes.
Reviewed-by: tbd, tbd
rev 6284 : [mq]: fixes-cleanup
*** 90,109 ****
//
// Local to this file.
class RefineCardTableEntryClosure: public CardTableEntryClosure {
- G1RemSet* _g1rs;
- ConcurrentG1Refine* _cg1r;
bool _concurrent;
public:
! RefineCardTableEntryClosure(G1RemSet* g1rs,
! ConcurrentG1Refine* cg1r) :
! _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
! {}
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
! bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false);
// This path is executed by the concurrent refine or mutator threads,
// concurrently, and so we do not care if card_ptr contains references
// that point into the collection set.
assert(!oops_into_cset, "should be");
--- 90,105 ----
//
// Local to this file.
class RefineCardTableEntryClosure: public CardTableEntryClosure {
bool _concurrent;
public:
! RefineCardTableEntryClosure() : _concurrent(true) { }
!
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
! bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false);
// This path is executed by the concurrent refine or mutator threads,
// concurrently, and so we do not care if card_ptr contains references
// that point into the collection set.
assert(!oops_into_cset, "should be");
*** 112,121 ****
--- 108,118 ----
return false;
}
// Otherwise, we finished successfully; return true.
return true;
}
+
void set_concurrent(bool b) { _concurrent = b; }
};
class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure {
*** 475,487 ****
ct_bs->mod_card_iterate(&count1);
int orig_count = count1.n();
// First clear the logged cards.
ClearLoggedCardTableEntryClosure clear;
! dcqs.set_closure(&clear);
! dcqs.apply_closure_to_all_completed_buffers();
! dcqs.iterate_closure_all_threads(false);
clear.print_histo();
// Now ensure that there's no dirty cards.
CountNonCleanMemRegionClosure count2(this);
ct_bs->mod_card_iterate(&count2);
--- 472,483 ----
ct_bs->mod_card_iterate(&count1);
int orig_count = count1.n();
// First clear the logged cards.
ClearLoggedCardTableEntryClosure clear;
! dcqs.apply_closure_to_all_completed_buffers(&clear);
! dcqs.iterate_closure_all_threads(&clear, false);
clear.print_histo();
// Now ensure that there's no dirty cards.
CountNonCleanMemRegionClosure count2(this);
ct_bs->mod_card_iterate(&count2);
*** 490,502 ****
count2.n(), orig_count);
}
guarantee(count2.n() == 0, "Card table should be clean.");
RedirtyLoggedCardTableEntryClosure redirty;
! JavaThread::dirty_card_queue_set().set_closure(&redirty);
! dcqs.apply_closure_to_all_completed_buffers();
! dcqs.iterate_closure_all_threads(false);
gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.",
clear.calls(), orig_count);
guarantee(redirty.calls() == clear.calls(),
"Or else mechanism is broken.");
--- 486,497 ----
count2.n(), orig_count);
}
guarantee(count2.n() == 0, "Card table should be clean.");
RedirtyLoggedCardTableEntryClosure redirty;
! dcqs.apply_closure_to_all_completed_buffers(&redirty);
! dcqs.iterate_closure_all_threads(&redirty, false);
gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.",
clear.calls(), orig_count);
guarantee(redirty.calls() == clear.calls(),
"Or else mechanism is broken.");
*** 505,516 ****
if (count3.n() != orig_count) {
gclog_or_tty->print_cr("Should have restored them all: orig = %d, final = %d.",
orig_count, count3.n());
guarantee(count3.n() >= orig_count, "Should have restored them all.");
}
-
- JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
}
// Private class members.
G1CollectedHeap* G1CollectedHeap::_g1h;
--- 500,509 ----
*** 2000,2010 ****
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
! _cg1r = new ConcurrentG1Refine(this);
// Reserve the maximum.
// When compressed oops are enabled, the preferred heap base
// is calculated by subtracting the requested size from the
--- 1993,2005 ----
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
! _refine_cte_cl = new RefineCardTableEntryClosure();
!
! _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl);
// Reserve the maximum.
// When compressed oops are enabled, the preferred heap base
// is calculated by subtracting the requested size from the
*** 2095,2132 ****
}
// Perform any initialization actions delegated to the policy.
g1_policy()->init();
- _refine_cte_cl =
- new RefineCardTableEntryClosure(g1_rem_set(),
- concurrent_g1_refine());
- JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
-
JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
SATB_Q_FL_lock,
G1SATBProcessCompletedThreshold,
Shared_SATB_Q_lock);
! JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
concurrent_g1_refine()->yellow_zone(),
concurrent_g1_refine()->red_zone(),
Shared_DirtyCardQ_lock);
if (G1DeferredRSUpdate) {
! dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
}
// Initialize the card queue set used to hold cards containing
// references into the collection set.
! _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
--- 2090,2125 ----
}
// Perform any initialization actions delegated to the policy.
g1_policy()->init();
JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
SATB_Q_FL_lock,
G1SATBProcessCompletedThreshold,
Shared_SATB_Q_lock);
! JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl,
! DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
concurrent_g1_refine()->yellow_zone(),
concurrent_g1_refine()->red_zone(),
Shared_DirtyCardQ_lock);
if (G1DeferredRSUpdate) {
! dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
! DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
}
// Initialize the card queue set used to hold cards containing
// references into the collection set.
! _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code
! DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
-1, // never trigger processing
-1, // no limit on length
Shared_DirtyCardQ_lock,
&JavaThread::dirty_card_queue_set());
*** 5260,5283 ****
G1StringDedup::unlink(is_alive);
}
}
class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
! public:
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
*card_ptr = CardTableModRefBS::dirty_card_val();
return true;
}
};
void G1CollectedHeap::redirty_logged_cards() {
guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
double redirty_logged_cards_start = os::elapsedTime();
! RedirtyLoggedCardTableEntryFastClosure redirty;
! dirty_card_queue_set().set_closure(&redirty);
! dirty_card_queue_set().apply_closure_to_all_completed_buffers();
DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
dcq.merge_bufferlists(&dirty_card_queue_set());
assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
--- 5253,5315 ----
G1StringDedup::unlink(is_alive);
}
}
class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
! private:
! size_t _num_processed;
!
! public:
! RedirtyLoggedCardTableEntryFastClosure() : CardTableEntryClosure(), _num_processed(0) { }
!
bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
*card_ptr = CardTableModRefBS::dirty_card_val();
+ _num_processed++;
return true;
}
+
+ size_t num_processed() const { return _num_processed; }
+ };
+
+ class G1RedirtyLoggedCardsTask : public AbstractGangTask {
+ private:
+ DirtyCardQueueSet* _queue;
+ public:
+ G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { }
+
+ virtual void work(uint worker_id) {
+ double start_time = os::elapsedTime();
+
+ RedirtyLoggedCardTableEntryFastClosure cl;
+ if (G1CollectedHeap::heap()->use_parallel_gc_threads()) {
+ _queue->par_apply_closure_to_all_completed_buffers(&cl);
+ } else {
+ _queue->apply_closure_to_all_completed_buffers(&cl);
+ }
+
+ G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times();
+ timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0);
+ timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed());
+ }
};
void G1CollectedHeap::redirty_logged_cards() {
guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
double redirty_logged_cards_start = os::elapsedTime();
! uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
! _g1h->workers()->active_workers() : 1);
!
! G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set());
! dirty_card_queue_set().reset_for_par_iteration();
! if (use_parallel_gc_threads()) {
! set_par_threads(n_workers);
! workers()->run_task(&redirty_task);
! set_par_threads(0);
! } else {
! redirty_task.work(0);
! }
DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
dcq.merge_bufferlists(&dirty_card_queue_set());
assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");