8315219: G1: Improve allocator pathological case where it keeps doing direct allocations instead of retiring a PLAB

Reviewed-by: tschatzl, ayang, mli
This commit is contained in:
Ivan Walulya 2023-08-31 08:04:47 +00:00
parent 218829e0a2
commit 47aa6f3a65
2 changed files with 17 additions and 15 deletions
src/hotspot/share/gc/g1
test/hotspot/jtreg/gc/g1/plab

@ -358,14 +358,18 @@ G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) :
}
}
bool G1PLABAllocator::may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const {
return (allocation_word_sz * 100 < buffer_size * ParallelGCBufferWastePct);
bool G1PLABAllocator::may_throw_away_buffer(size_t const words_remaining, size_t const buffer_size) const {
return (words_remaining * 100 < buffer_size * ParallelGCBufferWastePct);
}
HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
size_t word_sz,
bool* plab_refill_failed,
uint node_index) {
PLAB* alloc_buf = alloc_buffer(dest, node_index);
size_t words_remaining = alloc_buf->words_remaining();
assert(words_remaining < word_sz, "precondition");
size_t plab_word_size = plab_size(dest.type());
size_t next_plab_word_size = plab_word_size;
@ -378,13 +382,10 @@ HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(G1HeapRegionAttr dest,
size_t required_in_plab = PLAB::size_required_for_allocation(word_sz);
// Only get a new PLAB if the allocation fits into the to-be-allocated PLAB and
// it would not waste more than ParallelGCBufferWastePct in the current PLAB.
// Boosting the PLAB also increasingly allows more waste to occur.
// retiring the current PLAB would not waste more than ParallelGCBufferWastePct
// in the current PLAB. Boosting the PLAB also increasingly allows more waste to occur.
if ((required_in_plab <= next_plab_word_size) &&
may_throw_away_buffer(required_in_plab, plab_word_size)) {
PLAB* alloc_buf = alloc_buffer(dest, node_index);
guarantee(alloc_buf->words_remaining() <= required_in_plab, "must be");
may_throw_away_buffer(words_remaining, plab_word_size)) {
alloc_buf->retire();

@ -45,6 +45,7 @@ import gc.g1.plab.lib.LogParser;
import gc.g1.plab.lib.PLABUtils;
import gc.g1.plab.lib.PlabInfo;
import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
@ -62,17 +63,18 @@ public class TestPLABPromotion {
private final static String PLAB_DIRECT_ALLOCATED_FIELD_NAME = "direct allocated";
private final static List<String> FIELDS_TO_EXTRACT = Arrays.asList(PLAB_USED_FIELD_NAME, PLAB_DIRECT_ALLOCATED_FIELD_NAME);
private static final int HEAP_WORD_SIZE = Platform.is32bit() ? 4 : 8;
private static String output;
// Allowable difference for memory consumption (percentage)
private final static long MEM_DIFFERENCE_PCT = 5;
private static final int PLAB_SIZE_SMALL = 1024;
private static final int PLAB_SIZE_MEDIUM = 4096;
private static final int PLAB_SIZE_HIGH = 65536;
private static final int OBJECT_SIZE_SMALL = 10;
private static final int OBJECT_SIZE_MEDIUM = 100;
private static final int OBJECT_SIZE_HIGH = 3250;
private static final int OBJECT_SIZE_SMALL = 10 * HEAP_WORD_SIZE;
private static final int OBJECT_SIZE_MEDIUM = 128 * HEAP_WORD_SIZE;
private static final int OBJECT_SIZE_HIGH = 3072 * HEAP_WORD_SIZE;
private static final int GC_NUM_SMALL = 1;
private static final int GC_NUM_MEDIUM = 3;
private static final int GC_NUM_HIGH = 7;
@ -94,7 +96,8 @@ public class TestPLABPromotion {
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, false),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, false),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_FIXED, true, true),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_SMALL, OBJECT_SIZE_HIGH, GC_NUM_MEDIUM, YOUNG_SIZE_HIGH, PLAB_FIXED, true, false),
@ -104,8 +107,6 @@ public class TestPLABPromotion {
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_MEDIUM, OBJECT_SIZE_SMALL, GC_NUM_SMALL, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true),
new TestCase(WASTE_PCT_SMALL, PLAB_SIZE_MEDIUM, OBJECT_SIZE_HIGH, GC_NUM_HIGH, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, false),
new TestCase(WASTE_PCT_MEDIUM, PLAB_SIZE_SMALL, OBJECT_SIZE_MEDIUM, GC_NUM_MEDIUM, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_MEDIUM, GC_NUM_SMALL, YOUNG_SIZE_HIGH, PLAB_DYNAMIC, true, true),
new TestCase(WASTE_PCT_HIGH, PLAB_SIZE_HIGH, OBJECT_SIZE_SMALL, GC_NUM_HIGH, YOUNG_SIZE_LOW, PLAB_DYNAMIC, true, true)
};