8040162: Avoid reallocating PLABs between GC phases in G1

Allocate G1ParScanThreadState at the start of GC and only deallocate at the end of GC. This automatically keeps the current PLAB intact without flushing it (and loosing lots of memory) for every reallocation.

Reviewed-by: david, mgerdin
This commit is contained in:
Thomas Schatzl 2015-08-20 15:17:43 +02:00
parent 4a849fb21c
commit 6cca258181
7 changed files with 193 additions and 142 deletions

View file

@ -32,17 +32,17 @@
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp)
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
: _g1h(g1h),
_refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()),
_ct_bs(g1h->g1_barrier_set()),
_g1_rem(g1h->g1_rem_set()),
_hash_seed(17), _worker_id(worker_id),
_term_attempts(0),
_hash_seed(17),
_worker_id(worker_id),
_tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
_age_table(false), _scanner(g1h, rp),
_strong_roots_time(0), _term_time(0),
_age_table(false),
_scanner(g1h),
_old_gen_is_full(false)
{
_scanner.set_par_scan_thread_state(this);
@ -69,8 +69,6 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id,
// need to be moved to the next space.
_dest[InCSetState::Young] = InCSetState::Old;
_dest[InCSetState::Old] = InCSetState::Old;
_start = os::elapsedTime();
}
G1ParScanThreadState::~G1ParScanThreadState() {
@ -79,28 +77,8 @@ G1ParScanThreadState::~G1ParScanThreadState() {
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}
void G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) {
st->print_raw_cr("GC Termination Stats");
st->print_raw_cr(" elapsed --strong roots-- -------termination------- ------waste (KiB)------");
st->print_raw_cr("thr ms ms % ms % attempts total alloc undo");
st->print_raw_cr("--- --------- --------- ------ --------- ------ -------- ------- ------- -------");
}
void G1ParScanThreadState::print_termination_stats(outputStream* const st) const {
const double elapsed_ms = elapsed_time() * 1000.0;
const double s_roots_ms = strong_roots_time() * 1000.0;
const double term_ms = term_time() * 1000.0;
size_t alloc_buffer_waste = 0;
size_t undo_waste = 0;
_plab_allocator->waste(alloc_buffer_waste, undo_waste);
st->print_cr("%3u %9.2f %9.2f %6.2f "
"%9.2f %6.2f " SIZE_FORMAT_W(8) " "
SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
_worker_id, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
(alloc_buffer_waste + undo_waste) * HeapWordSize / K,
alloc_buffer_waste * HeapWordSize / K,
undo_waste * HeapWordSize / K);
void G1ParScanThreadState::waste(size_t& wasted, size_t& undo_wasted) {
_plab_allocator->waste(wasted, undo_wasted);
}
#ifdef ASSERT
@ -292,8 +270,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
obj);
}
size_t* const surv_young_words = surviving_young_words();
surv_young_words[young_index] += word_sz;
_surviving_young_words[young_index] += word_sz;
if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
// We keep track of the next start index in the length field of