8141141: Young and Old gen PLAB stats are similar in output with -XX:+PrintPLAB
Improve PLAB statistic by adding generation, output values are now in bytes, including units, and split it into multiple messages.
Reviewed-by: brutisso, sjohanss
diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
index 6962f15..366bf46 100644
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
@@ -615,7 +615,7 @@
: DefNewGeneration(rs, initial_byte_size, "PCopy"),
_overflow_list(NULL),
_is_alive_closure(this),
- _plab_stats(YoungPLABSize, PLABWeight)
+ _plab_stats("Young", YoungPLABSize, PLABWeight)
{
NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;)
NOT_PRODUCT(_num_par_pushes = 0;)
@@ -1008,9 +1008,7 @@
from()->set_concurrent_iteration_safe_limit(from()->top());
to()->set_concurrent_iteration_safe_limit(to()->top());
- if (ResizePLAB) {
- plab_stats()->adjust_desired_plab_sz();
- }
+ plab_stats()->adjust_desired_plab_sz();
TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats());
TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats());
diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
index 2c0f452..743bdd5 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
@@ -1760,8 +1760,8 @@
_young_list(new YoungList(this)),
_gc_time_stamp(0),
_summary_bytes_used(0),
- _survivor_evac_stats(YoungPLABSize, PLABWeight),
- _old_evac_stats(OldPLABSize, PLABWeight),
+ _survivor_evac_stats("Young", YoungPLABSize, PLABWeight),
+ _old_evac_stats("Old", OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true),
_old_marking_cycles_started(0),
_old_marking_cycles_completed(0),
diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp
index a000a1e..1cb7384 100644
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -29,15 +29,26 @@
#include "logging/log.hpp"
#include "trace/tracing.hpp"
+void G1EvacStats::log_plab_allocation() {
+ PLABStats::log_plab_allocation();
+ log_debug(gc, plab)("%s other allocation: "
+ "region end waste: " SIZE_FORMAT "B, "
+ "regions filled: %u, "
+ "direct allocated: " SIZE_FORMAT "B, "
+ "failure used: " SIZE_FORMAT "B, "
+ "failure wasted: " SIZE_FORMAT "B",
+ _description,
+ _region_end_waste * HeapWordSize,
+ _regions_filled,
+ _direct_allocated * HeapWordSize,
+ _failure_used * HeapWordSize,
+ _failure_waste * HeapWordSize);
+}
+
void G1EvacStats::adjust_desired_plab_sz() {
+ log_plab_allocation();
+
if (!ResizePLAB) {
- log_debug(gc, plab)(" (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);
// Clear accumulators for next round.
reset();
return;
@@ -107,18 +118,19 @@
// Latch the result
_desired_net_plab_sz = plab_sz;
- log_debug(gc, plab)(" (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 ") "
- " (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ")",
- _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste,
- _regions_filled, _direct_allocated, _failure_used, _failure_waste,
- cur_plab_sz, plab_sz);
-
+ log_sizing(cur_plab_sz, plab_sz);
// Clear accumulators for next round.
reset();
}
+G1EvacStats::G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt) :
+ PLABStats(description, desired_plab_sz_, wt),
+ _region_end_waste(0),
+ _regions_filled(0),
+ _direct_allocated(0),
+ _failure_used(0),
+ _failure_waste(0) {
+}
+
+
G1EvacStats::~G1EvacStats() { }
diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp
index 1d0a53f..b322593 100644
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -51,20 +51,15 @@
_failure_waste = 0;
}
+ virtual void log_plab_allocation();
+
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) {
- }
+ G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt);
+
+ ~G1EvacStats();
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; }
@@ -77,8 +72,6 @@
inline void add_direct_allocated(size_t value);
inline void add_region_end_waste(size_t value);
inline void add_failure_used_and_waste(size_t used, size_t waste);
-
- ~G1EvacStats();
};
#endif // SHARE_VM_GC_G1_G1EVACSTATS_HPP
diff --git a/hotspot/src/share/vm/gc/shared/plab.cpp b/hotspot/src/share/vm/gc/shared/plab.cpp
index d856652..1743bff 100644
--- a/hotspot/src/share/vm/gc/shared/plab.cpp
+++ b/hotspot/src/share/vm/gc/shared/plab.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -110,6 +110,30 @@
}
}
+void PLABStats::log_plab_allocation() {
+ log_debug(gc, plab)("%s PLAB allocation: "
+ "allocated: " SIZE_FORMAT "B, "
+ "wasted: " SIZE_FORMAT "B, "
+ "unused: " SIZE_FORMAT "B, "
+ "used: " SIZE_FORMAT "B, "
+ "undo waste: " SIZE_FORMAT "B, ",
+ _description,
+ _allocated * HeapWordSize,
+ _wasted * HeapWordSize,
+ _unused * HeapWordSize,
+ used() * HeapWordSize,
+ _undo_wasted * HeapWordSize);
+}
+
+void PLABStats::log_sizing(size_t calculated_words, size_t net_desired_words) {
+ log_debug(gc, plab)("%s sizing: "
+ "calculated: " SIZE_FORMAT "B, "
+ "actual: " SIZE_FORMAT "B",
+ _description,
+ calculated_words * HeapWordSize,
+ net_desired_words * HeapWordSize);
+}
+
// Calculates plab size for current number of gc worker threads.
size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) {
return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers));
@@ -119,7 +143,13 @@
// use. This should be called once at the end of parallel
// scavenge; it clears the sensor accumulators.
void PLABStats::adjust_desired_plab_sz() {
- assert(ResizePLAB, "Not set");
+ log_plab_allocation();
+
+ if (!ResizePLAB) {
+ // Clear accumulators for next round.
+ reset();
+ return;
+ }
assert(is_object_aligned(max_size()) && min_size() <= max_size(),
"PLAB clipping computation may be incorrect");
@@ -150,8 +180,9 @@
new_plab_sz = MIN2(max_size(), new_plab_sz);
new_plab_sz = align_object_size(new_plab_sz);
// Latch the result
- log_trace(gc, plab)("plab_size = " SIZE_FORMAT " desired_net_plab_sz = " SIZE_FORMAT ") ", recent_plab_sz, new_plab_sz);
_desired_net_plab_sz = new_plab_sz;
+ log_sizing(recent_plab_sz, new_plab_sz);
+
reset();
}
diff --git a/hotspot/src/share/vm/gc/shared/plab.hpp b/hotspot/src/share/vm/gc/shared/plab.hpp
index b684769..e73562b 100644
--- a/hotspot/src/share/vm/gc/shared/plab.hpp
+++ b/hotspot/src/share/vm/gc/shared/plab.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -146,6 +146,8 @@
// PLAB book-keeping.
class PLABStats : public CHeapObj<mtGC> {
protected:
+ const char* _description; // Identifying string.
+
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)
@@ -160,8 +162,12 @@
_undo_wasted = 0;
_unused = 0;
}
+
+ virtual void log_plab_allocation();
+ virtual void log_sizing(size_t calculated, size_t net_desired);
public:
- PLABStats(size_t desired_net_plab_sz_, unsigned wt) :
+ PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) :
+ _description(description),
_allocated(0),
_wasted(0),
_undo_wasted(0),
@@ -172,6 +178,12 @@
virtual ~PLABStats() { }
+ 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; }
+
static const size_t min_size() {
return PLAB::min_size();
}
diff --git a/hotspot/test/gc/g1/TestPLABOutput.java b/hotspot/test/gc/g1/TestPLABOutput.java
index a8265ac..4b85b1c 100644
--- a/hotspot/test/gc/g1/TestPLABOutput.java
+++ b/hotspot/test/gc/g1/TestPLABOutput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -65,7 +65,7 @@
System.out.println(output.getStdout());
- String pattern = ".*GC\\(0\\) .*allocated = (\\d+).*";
+ String pattern = ".*GC\\(0\\) .*allocated: (\\d+).*";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(output.getStdout());
diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java
index 54a56bb..7b892f2 100644
--- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java
+++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java
@@ -23,7 +23,7 @@
/*
* @test TestPLABPromotion
- * @bug 8141278
+ * @bug 8141278 8141141
* @summary Test PLAB promotion
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.FlightRecorder != true
@@ -130,16 +130,15 @@
long plabAllocatedOld;
long directAllocatedOld;
long memAllocated = testCase.getMemToFill();
- long wordSize = Platform.is32bit() ? 4l : 8l;
LogParser logParser = new LogParser(output);
Map<String, Long> survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS);
Map<String, Long> oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS);
- plabAllocatedSurvivor = wordSize * survivorStats.get("used");
- directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated");
- plabAllocatedOld = wordSize * oldStats.get("used");
- directAllocatedOld = wordSize * oldStats.get("direct_allocated");
+ plabAllocatedSurvivor = survivorStats.get("used");
+ directAllocatedSurvivor = survivorStats.get("direct allocated");
+ plabAllocatedOld = oldStats.get("used");
+ directAllocatedOld = oldStats.get("direct allocated");
System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated);
System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated);
diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java
index b07b769..e9aef79 100644
--- a/hotspot/test/gc/g1/plab/TestPLABResize.java
+++ b/hotspot/test/gc/g1/plab/TestPLABResize.java
@@ -23,7 +23,7 @@
/*
* @test TestPLABResize
- * @bug 8141278
+ * @bug 8141278 8141141
* @summary Test for PLAB resizing
* @requires vm.gc=="G1" | vm.gc=="null"
* @requires vm.opt.FlightRecorder != true
@@ -117,7 +117,7 @@
.map(item -> {
return item.getValue()
.get(LogParser.ReportType.SURVIVOR_STATS)
- .get("desired_plab_sz");
+ .get("actual");
})
.collect(Collectors.toCollection(ArrayList::new));
diff --git a/hotspot/test/gc/g1/plab/lib/LogParser.java b/hotspot/test/gc/g1/plab/lib/LogParser.java
index ce2f94e..2bf933e 100644
--- a/hotspot/test/gc/g1/plab/lib/LogParser.java
+++ b/hotspot/test/gc/g1/plab/lib/LogParser.java
@@ -35,14 +35,12 @@
*
* Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like:
*
- * [2,244s][info ][gc ] GC(30) Concurrent Mark abort
- * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
- * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
- * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms
- * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
- * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258)
- * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms
-
+ * [0.330s][debug][gc,plab ] GC(0) Young PLAB allocation: allocated: 1825632B, wasted: 29424B, unused: 2320B, used: 1793888B, undo waste: 0B,
+ * [0.330s][debug][gc,plab ] GC(0) Young other allocation: region end waste: 0B, regions filled: 2, direct allocated: 271520B, failure used: 0B, failure wasted: 0B
+ * [0.330s][debug][gc,plab ] GC(0) Young sizing: calculated: 358776B, actual: 358776B
+ * [0.330s][debug][gc,plab ] GC(0) Old PLAB allocation: allocated: 427248B, wasted: 592B, unused: 368584B, used: 58072B, undo waste: 0B,
+ * [0.330s][debug][gc,plab ] GC(0) Old other allocation: region end waste: 0B, regions filled: 1, direct allocated: 41704B, failure used: 0B, failure wasted: 0B
+ * [0.330s][debug][gc,plab ] GC(0) Old sizing: calculated: 11608B, actual: 11608B
*/
final public class LogParser {
@@ -53,7 +51,6 @@
* Type of parsed log element.
*/
public static enum ReportType {
-
SURVIVOR_STATS,
OLD_STATS
}
@@ -64,8 +61,8 @@
// GC ID
private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)");
- // Pattern for extraction pair <name>=<numeric value>
- private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+");
+ // Pattern for extraction pair <name>: <numeric value>
+ private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w* \\w+:\\s+\\d+");
/**
* Construct LogParser Object
@@ -108,24 +105,29 @@
if (matcher.find()) {
Map<ReportType,Map<String, Long>> oneReportItem;
ReportType reportType;
- // Second line in log is statistics for Old PLAB allocation
- if ( !allocationStatistics.containsKey(gc_id.get()) ) {
- oneReportItem = new EnumMap<>(ReportType.class);
+
+ if (!allocationStatistics.containsKey(gc_id.get())) {
+ allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class));
+ }
+
+ if ( line.contains("Young") ) {
reportType = ReportType.SURVIVOR_STATS;
- allocationStatistics.put(gc_id.get(), oneReportItem);
} else {
- oneReportItem = allocationStatistics.get(gc_id.get());
reportType = ReportType.OLD_STATS;
}
+ oneReportItem = allocationStatistics.get(gc_id.get());
+ if (!oneReportItem.containsKey(reportType)) {
+ oneReportItem.put(reportType,new HashMap<String, Long>());
+ }
+
// Extract all pairs from log.
- HashMap<String, Long> plabStats = new HashMap<>();
+ Map<String, Long> plabStats = oneReportItem.get(reportType);
do {
String pair = matcher.group();
- String[] nameValue = pair.replaceAll(" ", "").split("=");
- plabStats.put(nameValue[0], Long.parseLong(nameValue[1]));
+ String[] nameValue = pair.replaceAll(": ", ":").split(":");
+ plabStats.put(nameValue[0].trim(), Long.parseLong(nameValue[1]));
} while (matcher.find());
- oneReportItem.put(reportType,plabStats);
}
}
}