8073013: Add detailed information about PLAB memory usage
Summary: Track and provide information about direct allocation, region end waste and failure waste for G1.
Reviewed-by: jmasa, david, ehelin, mgerdin
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Wed Aug 19 13:59:39 2015 +0200
@@ -46,10 +46,11 @@
_dummy_region = dummy_region;
}
-void G1AllocRegion::fill_up_remaining_space(HeapRegion* alloc_region,
- bool bot_updates) {
+size_t G1AllocRegion::fill_up_remaining_space(HeapRegion* alloc_region,
+ bool bot_updates) {
assert(alloc_region != NULL && alloc_region != _dummy_region,
"pre-condition");
+ size_t result = 0;
// Other threads might still be trying to allocate using a CAS out
// of the region we are trying to retire, as they can do so without
@@ -73,6 +74,7 @@
// If the allocation was successful we should fill in the space.
CollectedHeap::fill_with_object(dummy, free_word_size);
alloc_region->set_pre_dummy_top(dummy);
+ result += free_word_size * HeapWordSize;
break;
}
@@ -81,13 +83,18 @@
// allocation and they fill up the region. In that case, we can
// just get out of the loop.
}
+ result += alloc_region->free();
+
assert(alloc_region->free() / HeapWordSize < min_word_size_to_fill,
"post-condition");
+ return result;
}
-void G1AllocRegion::retire(bool fill_up) {
+size_t G1AllocRegion::retire(bool fill_up) {
assert(_alloc_region != NULL, ar_ext_msg(this, "not initialized properly"));
+ size_t result = 0;
+
trace("retiring");
HeapRegion* alloc_region = _alloc_region;
if (alloc_region != _dummy_region) {
@@ -98,7 +105,7 @@
ar_ext_msg(this, "the alloc region should never be empty"));
if (fill_up) {
- fill_up_remaining_space(alloc_region, _bot_updates);
+ result = fill_up_remaining_space(alloc_region, _bot_updates);
}
assert(alloc_region->used() >= _used_bytes_before,
@@ -109,6 +116,8 @@
_alloc_region = _dummy_region;
}
trace("retired");
+
+ return result;
}
HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size,
@@ -251,26 +260,25 @@
_g1h->retire_mutator_alloc_region(alloc_region, allocated_bytes);
}
-HeapRegion* SurvivorGCAllocRegion::allocate_new_region(size_t word_size,
- bool force) {
+HeapRegion* G1GCAllocRegion::allocate_new_region(size_t word_size,
+ bool force) {
assert(!force, "not supported for GC alloc regions");
- return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Young);
+ return _g1h->new_gc_alloc_region(word_size, count(), _purpose);
}
-void SurvivorGCAllocRegion::retire_region(HeapRegion* alloc_region,
- size_t allocated_bytes) {
- _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Young);
+void G1GCAllocRegion::retire_region(HeapRegion* alloc_region,
+ size_t allocated_bytes) {
+ _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, _purpose);
}
-HeapRegion* OldGCAllocRegion::allocate_new_region(size_t word_size,
- bool force) {
- assert(!force, "not supported for GC alloc regions");
- return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Old);
-}
-
-void OldGCAllocRegion::retire_region(HeapRegion* alloc_region,
- size_t allocated_bytes) {
- _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Old);
+size_t G1GCAllocRegion::retire(bool fill_up) {
+ HeapRegion* retired = get();
+ size_t end_waste = G1AllocRegion::retire(fill_up);
+ // Do not count retirement of the dummy allocation region.
+ if (retired != NULL) {
+ _stats->add_region_end_waste(end_waste / HeapWordSize);
+ }
+ return end_waste;
}
HeapRegion* OldGCAllocRegion::release() {
--- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -26,6 +26,8 @@
#define SHARE_VM_GC_G1_G1ALLOCREGION_HPP
#include "gc/g1/heapRegion.hpp"
+#include "gc/g1/g1EvacStats.hpp"
+#include "gc/g1/g1InCSetState.hpp"
class G1CollectedHeap;
@@ -105,13 +107,10 @@
// Ensure that the region passed as a parameter has been filled up
// so that noone else can allocate out of it any more.
- static void fill_up_remaining_space(HeapRegion* alloc_region,
- bool bot_updates);
-
- // Retire the active allocating region. If fill_up is true then make
- // sure that the region is full before we retire it so that noone
- // else can allocate out of it.
- void retire(bool fill_up);
+ // Returns the number of bytes that have been wasted by filled up
+ // the space.
+ static size_t fill_up_remaining_space(HeapRegion* alloc_region,
+ bool bot_updates);
// After a region is allocated by alloc_new_region, this
// method is used to set it as the active alloc_region
@@ -126,6 +125,12 @@
void fill_in_ext_msg(ar_ext_msg* msg, const char* message);
protected:
+ // Retire the active allocating region. If fill_up is true then make
+ // sure that the region is full before we retire it so that no one
+ // else can allocate out of it.
+ // Returns the number of bytes that have been filled up during retire.
+ virtual size_t retire(bool fill_up);
+
// For convenience as subclasses use it.
static G1CollectedHeap* _g1h;
@@ -201,22 +206,33 @@
: G1AllocRegion("Mutator Alloc Region", false /* bot_updates */) { }
};
-class SurvivorGCAllocRegion : public G1AllocRegion {
+// Common base class for allocation regions used during GC.
+class G1GCAllocRegion : public G1AllocRegion {
protected:
+ G1EvacStats* _stats;
+ InCSetState::in_cset_state_t _purpose;
+
virtual HeapRegion* allocate_new_region(size_t word_size, bool force);
virtual void retire_region(HeapRegion* alloc_region, size_t allocated_bytes);
+
+ virtual size_t retire(bool fill_up);
public:
- SurvivorGCAllocRegion()
- : G1AllocRegion("Survivor GC Alloc Region", false /* bot_updates */) { }
+ G1GCAllocRegion(const char* name, bool bot_updates, G1EvacStats* stats, InCSetState::in_cset_state_t purpose)
+ : G1AllocRegion(name, bot_updates), _stats(stats), _purpose(purpose) {
+ assert(stats != NULL, "Must pass non-NULL PLAB statistics");
+ }
};
-class OldGCAllocRegion : public G1AllocRegion {
-protected:
- virtual HeapRegion* allocate_new_region(size_t word_size, bool force);
- virtual void retire_region(HeapRegion* alloc_region, size_t allocated_bytes);
+class SurvivorGCAllocRegion : public G1GCAllocRegion {
public:
- OldGCAllocRegion()
- : G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { }
+ SurvivorGCAllocRegion(G1EvacStats* stats)
+ : G1GCAllocRegion("Survivor GC Alloc Region", false /* bot_updates */, stats, InCSetState::Young) { }
+};
+
+class OldGCAllocRegion : public G1GCAllocRegion {
+public:
+ OldGCAllocRegion(G1EvacStats* stats)
+ : G1GCAllocRegion("Old GC Alloc Region", true /* bot_updates */, stats, InCSetState::Old) { }
// This specialization of release() makes sure that the last card that has
// been allocated into has been completely filled by a dummy object. This
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Wed Aug 19 13:59:39 2015 +0200
@@ -30,6 +30,13 @@
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionSet.inline.hpp"
+G1DefaultAllocator::G1DefaultAllocator(G1CollectedHeap* heap) :
+ G1Allocator(heap),
+ _retained_old_gc_alloc_region(NULL),
+ _survivor_gc_alloc_region(heap->alloc_buffer_stats(InCSetState::Young)),
+ _old_gc_alloc_region(heap->alloc_buffer_stats(InCSetState::Old)) {
+}
+
void G1DefaultAllocator::init_mutator_alloc_region() {
assert(_mutator_alloc_region.get() == NULL, "pre-condition");
_mutator_alloc_region.init();
@@ -103,10 +110,8 @@
_retained_old_gc_alloc_region->record_retained_region();
}
- if (ResizePLAB) {
- _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz();
- _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz();
- }
+ _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz();
+ _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz();
}
void G1DefaultAllocator::abandon_gc_alloc_regions() {
@@ -213,6 +218,9 @@
_g1h(G1CollectedHeap::heap()),
_allocator(allocator),
_survivor_alignment_bytes(calc_survivor_alignment_bytes()) {
+ for (size_t i = 0; i < ARRAY_SIZE(_direct_allocated); i++) {
+ _direct_allocated[i] = 0;
+ }
}
HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(InCSetState dest,
@@ -237,8 +245,12 @@
// Otherwise.
*plab_refill_failed = true;
}
- // Try inline allocation.
- return _allocator->par_allocate_during_gc(dest, word_sz, context);
+ // Try direct allocation.
+ HeapWord* result = _allocator->par_allocate_during_gc(dest, word_sz, context);
+ if (result != NULL) {
+ _direct_allocated[dest.value()] += word_sz;
+ }
+ return result;
}
void G1PLABAllocator::undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) {
@@ -256,11 +268,14 @@
_alloc_buffers[InCSetState::Old] = &_tenured_alloc_buffer;
}
-void G1DefaultPLABAllocator::retire_alloc_buffers() {
+void G1DefaultPLABAllocator::flush_and_retire_stats() {
for (uint state = 0; state < InCSetState::Num; state++) {
G1PLAB* const buf = _alloc_buffers[state];
if (buf != NULL) {
- buf->flush_and_retire_stats(_g1h->alloc_buffer_stats(state));
+ G1EvacStats* stats = _g1h->alloc_buffer_stats(state);
+ buf->flush_and_retire_stats(stats);
+ stats->add_direct_allocated(_direct_allocated[state]);
+ _direct_allocated[state] = 0;
}
}
}
--- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -123,7 +123,7 @@
HeapRegion* _retained_old_gc_alloc_region;
public:
- G1DefaultAllocator(G1CollectedHeap* heap) : G1Allocator(heap), _retained_old_gc_alloc_region(NULL) { }
+ G1DefaultAllocator(G1CollectedHeap* heap);
virtual void init_mutator_alloc_region();
virtual void release_mutator_alloc_region();
@@ -172,6 +172,10 @@
guarantee(_retired, "Allocation buffer has not been retired");
}
+ // The amount of space in words wasted within the PLAB including
+ // waste due to refills and alignment.
+ size_t wasted() const { return _wasted; }
+
virtual void set_buf(HeapWord* buf) {
PLAB::set_buf(buf);
_retired = false;
@@ -207,7 +211,10 @@
// architectures have a special compare against zero instructions.
const uint _survivor_alignment_bytes;
- virtual void retire_alloc_buffers() = 0;
+ // Number of words allocated directly (not counting PLAB allocation).
+ size_t _direct_allocated[InCSetState::Num];
+
+ virtual void flush_and_retire_stats() = 0;
virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0;
// Calculate the survivor space object alignment in bytes. Returns that or 0 if
@@ -283,7 +290,7 @@
return _alloc_buffers[dest.value()];
}
- virtual void retire_alloc_buffers();
+ virtual void flush_and_retire_stats();
virtual void waste(size_t& wasted, size_t& undo_wasted);
};
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Aug 19 13:59:39 2015 +0200
@@ -1944,8 +1944,8 @@
_young_list(new YoungList(this)),
_gc_time_stamp(0),
_summary_bytes_used(0),
- _survivor_plab_stats(YoungPLABSize, PLABWeight),
- _old_plab_stats(OldPLABSize, PLABWeight),
+ _survivor_evac_stats(YoungPLABSize, PLABWeight),
+ _old_evac_stats(OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true),
_surviving_young_words(NULL),
_old_marking_cycles_started(0),
@@ -5972,6 +5972,11 @@
cur->set_evacuation_failed(false);
// The region is now considered to be old.
cur->set_old();
+ // Do some allocation statistics accounting. Regions that failed evacuation
+ // are always made old, so there is no need to update anything in the young
+ // gen statistics, but we need to update old gen statistics.
+ size_t used_words = cur->marked_bytes() / HeapWordSize;
+ _old_evac_stats.add_failure_used_and_waste(used_words, HeapRegion::GrainWords - used_words);
_old_set.add(cur);
evacuation_info.increment_collectionset_used_after(cur->used());
}
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -33,6 +33,7 @@
#include "gc/g1/g1HRPrinter.hpp"
#include "gc/g1/g1InCSetState.hpp"
#include "gc/g1/g1MonitoringSupport.hpp"
+#include "gc/g1/g1EvacStats.hpp"
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/g1YCTypes.hpp"
#include "gc/g1/hSpaceCounters.hpp"
@@ -186,8 +187,7 @@
friend class VM_G1IncCollectionPause;
friend class VMStructs;
friend class MutatorAllocRegion;
- friend class SurvivorGCAllocRegion;
- friend class OldGCAllocRegion;
+ friend class G1GCAllocRegion;
// Closures used in implementation.
friend class G1ParScanThreadState;
@@ -247,7 +247,7 @@
// The sequence of all heap regions in the heap.
HeapRegionManager _hrm;
- // Handles non-humongous allocations in the G1CollectedHeap.
+ // Manages all allocations with regions except humongous object allocations.
G1Allocator* _allocator;
// Outside of GC pauses, the number of bytes used in all regions other
@@ -265,11 +265,11 @@
// Statistics for each allocation context
AllocationContextStats _allocation_context_stats;
- // PLAB sizing policy for survivors.
- PLABStats _survivor_plab_stats;
+ // GC allocation statistics policy for survivors.
+ G1EvacStats _survivor_evac_stats;
- // PLAB sizing policy for tenured objects.
- PLABStats _old_plab_stats;
+ // GC allocation statistics policy for tenured objects.
+ G1EvacStats _old_evac_stats;
// It specifies whether we should attempt to expand the heap after a
// region allocation failure. If heap expansion fails we set this to
@@ -608,7 +608,7 @@
bool expand(size_t expand_bytes);
// Returns the PLAB statistics for a given destination.
- inline PLABStats* alloc_buffer_stats(InCSetState dest);
+ inline G1EvacStats* alloc_buffer_stats(InCSetState dest);
// Determines PLAB size for a given destination.
inline size_t desired_plab_sz(InCSetState dest);
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -35,12 +35,12 @@
#include "gc/shared/taskqueue.hpp"
#include "runtime/orderAccess.inline.hpp"
-PLABStats* G1CollectedHeap::alloc_buffer_stats(InCSetState dest) {
+G1EvacStats* G1CollectedHeap::alloc_buffer_stats(InCSetState dest) {
switch (dest.value()) {
case InCSetState::Young:
- return &_survivor_plab_stats;
+ return &_survivor_evac_stats;
case InCSetState::Old:
- return &_old_plab_stats;
+ return &_old_evac_stats;
default:
ShouldNotReachHere();
return NULL; // Keep some compilers happy
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Wed Aug 19 13:59:39 2015 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1EvacStats.hpp"
+#include "gc/shared/gcId.hpp"
+#include "trace/tracing.hpp"
+
+void G1EvacStats::adjust_desired_plab_sz() {
+ if (PrintPLAB) {
+ gclog_or_tty->print(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " "
+ "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " "
+ "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " "
+ "regions filled = %u direct_allocated = " SIZE_FORMAT " "
+ "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ",
+ _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste,
+ _regions_filled, _direct_allocated, _failure_used, _failure_waste);
+ }
+
+ if (ResizePLAB) {
+
+ assert(is_object_aligned(max_size()) && min_size() <= max_size(),
+ "PLAB clipping computation may be incorrect");
+
+ if (_allocated == 0) {
+ assert((_unused == 0),
+ err_msg("Inconsistency in PLAB stats: "
+ "_allocated: "SIZE_FORMAT", "
+ "_wasted: "SIZE_FORMAT", "
+ "_region_end_waste: "SIZE_FORMAT", "
+ "_unused: "SIZE_FORMAT", "
+ "_used : "SIZE_FORMAT,
+ _allocated, _wasted, _region_end_waste, _unused, used()));
+ _allocated = 1;
+ }
+ // We account region end waste fully to PLAB allocation. This is not completely fair,
+ // but is a conservative assumption because PLABs may be sized flexibly while we
+ // cannot adjust direct allocations.
+ // In some cases, wasted_frac may become > 1 but that just reflects the problem
+ // with region_end_waste.
+ double wasted_frac = (double)(_unused + _wasted + _region_end_waste) / (double)_allocated;
+ size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct);
+ if (target_refills == 0) {
+ target_refills = 1;
+ }
+ size_t cur_plab_sz = used() / target_refills;
+ // Take historical weighted average
+ _filter.sample(cur_plab_sz);
+ // Clip from above and below, and align to object boundary
+ size_t plab_sz;
+ plab_sz = MAX2(min_size(), (size_t)_filter.average());
+ plab_sz = MIN2(max_size(), plab_sz);
+ plab_sz = align_object_size(plab_sz);
+ // Latch the result
+ _desired_net_plab_sz = plab_sz;
+ if (PrintPLAB) {
+ gclog_or_tty->print_cr(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz);
+ }
+ }
+ // Clear accumulators for next round.
+ reset();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_gc_G1_G1EVACSTATS_HPP
+#define SHARE_VM_gc_G1_G1EVACSTATS_HPP
+
+#include "gc/shared/plab.hpp"
+#include "runtime/atomic.hpp"
+
+// Records various memory allocation statistics gathered during evacuation.
+class G1EvacStats : public PLABStats {
+ private:
+ size_t _region_end_waste; // Number of words wasted due to skipping to the next region.
+ uint _regions_filled; // Number of regions filled completely.
+ size_t _direct_allocated; // Number of words allocated directly into the regions.
+
+ // Number of words in live objects remaining in regions that ultimately suffered an
+ // evacuation failure. This is used in the regions when the regions are made old regions.
+ size_t _failure_used;
+ // Number of words wasted in regions which failed evacuation. This is the sum of space
+ // for objects successfully copied out of the regions (now dead space) plus waste at the
+ // end of regions.
+ size_t _failure_waste;
+
+ virtual void reset() {
+ PLABStats::reset();
+ _region_end_waste = 0;
+ _regions_filled = 0;
+ _direct_allocated = 0;
+ _failure_used = 0;
+ _failure_waste = 0;
+ }
+
+ public:
+ G1EvacStats(size_t desired_plab_sz_, unsigned wt) : PLABStats(desired_plab_sz_, wt),
+ _region_end_waste(0), _regions_filled(0), _direct_allocated(0),
+ _failure_used(0), _failure_waste(0) {
+ }
+
+ virtual void adjust_desired_plab_sz();
+
+ size_t allocated() const { return _allocated; }
+ size_t wasted() const { return _wasted; }
+ size_t unused() const { return _unused; }
+ size_t used() const { return allocated() - (wasted() + unused()); }
+ size_t undo_wasted() const { return _undo_wasted; }
+
+ uint regions_filled() const { return _regions_filled; }
+ size_t region_end_waste() const { return _region_end_waste; }
+ size_t direct_allocated() const { return _direct_allocated; }
+
+ // Amount of space in heapwords used in the failing regions when an evacuation failure happens.
+ size_t failure_used() const { return _failure_used; }
+ // Amount of space in heapwords wasted (unused) in the failing regions when an evacuation failure happens.
+ size_t failure_waste() const { return _failure_waste; }
+
+ void add_direct_allocated(size_t value) {
+ Atomic::add_ptr(value, &_direct_allocated);
+ }
+
+ void add_region_end_waste(size_t value) {
+ Atomic::add_ptr(value, &_region_end_waste);
+ Atomic::add_ptr(1, &_regions_filled);
+ }
+
+ void add_failure_used_and_waste(size_t used, size_t waste) {
+ Atomic::add_ptr(used, &_failure_used);
+ Atomic::add_ptr(waste, &_failure_waste);
+ }
+};
+
+#endif // SHARE_VM_gc_G1_G1EVACSTATS_HPP
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Wed Aug 19 13:59:39 2015 +0200
@@ -74,7 +74,7 @@
}
G1ParScanThreadState::~G1ParScanThreadState() {
- _plab_allocator->retire_alloc_buffers();
+ _plab_allocator->flush_and_retire_stats();
delete _plab_allocator;
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}
--- a/hotspot/src/share/vm/gc/shared/plab.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/plab.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -27,7 +27,6 @@
#include "gc/shared/gcUtil.hpp"
#include "memory/allocation.hpp"
-#include "runtime/atomic.hpp"
#include "utilities/globalDefinitions.hpp"
// Forward declarations.
@@ -149,7 +148,8 @@
};
// PLAB book-keeping.
-class PLABStats VALUE_OBJ_CLASS_SPEC {
+class PLABStats : public CHeapObj<mtGC> {
+ protected:
size_t _allocated; // Total allocated
size_t _wasted; // of which wasted (internal fragmentation)
size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size)
@@ -158,7 +158,7 @@
AdaptiveWeightedAverage
_filter; // Integrator with decay
- void reset() {
+ virtual void reset() {
_allocated = 0;
_wasted = 0;
_undo_wasted = 0;
@@ -174,6 +174,8 @@
_filter(wt)
{ }
+ virtual ~PLABStats() { }
+
static const size_t min_size() {
return PLAB::min_size();
}
@@ -187,7 +189,7 @@
// Updates the current desired PLAB size. Computes the new desired PLAB size with one gc worker thread,
// updates _desired_plab_sz and clears sensor accumulators.
- void adjust_desired_plab_sz();
+ virtual void adjust_desired_plab_sz();
inline void add_allocated(size_t v);
--- a/hotspot/src/share/vm/gc/shared/plab.inline.hpp Wed Aug 19 13:50:50 2015 +0200
+++ b/hotspot/src/share/vm/gc/shared/plab.inline.hpp Wed Aug 19 13:59:39 2015 +0200
@@ -27,6 +27,7 @@
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/plab.hpp"
+#include "memory/allocation.inline.hpp"
#include "runtime/atomic.inline.hpp"
inline HeapWord* PLAB::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) {