7027766: G1: introduce flag to dump the liveness information per region at the end of marking

Repurpose the existing flag G1PrintRegionLivenessInfo to print out the liveness distribution across the regions in the heap at the end of marking.

Reviewed-by: iveresov, jwilhelm
This commit is contained in:
Antonios Printezis 2011-04-04 14:23:17 -04:00
parent cec5c20656
commit f418b77aa6
7 changed files with 249 additions and 55 deletions

View file

@ -1204,7 +1204,6 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
g1p->record_concurrent_mark_remark_end();
}
#define CARD_BM_TEST_MODE 0
class CalcLiveObjectsClosure: public HeapRegionClosure {
@ -1726,6 +1725,11 @@ void ConcurrentMark::cleanup() {
}
_total_counting_time += this_final_counting_time;
if (G1PrintRegionLivenessInfo) {
G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Marking");
_g1h->heap_region_iterate(&cl);
}
// Install newly created mark bitMap as "prev".
swapMarkBitMaps();
@ -4423,3 +4427,175 @@ CMTask::CMTask(int task_id,
_marking_step_diffs_ms.add(0.5);
}
// These are formatting macros that are used below to ensure
// consistent formatting. The *_H_* versions are used to format the
// header for a particular value and they should be kept consistent
// with the corresponding macro. Also note that most of the macros add
// the necessary white space (as a prefix) which makes them a bit
// easier to compose.
// All the output lines are prefixed with this string to be able to
// identify them easily in a large log file.
#define G1PPRL_LINE_PREFIX "###"
#define G1PPRL_ADDR_BASE_FORMAT " "PTR_FORMAT"-"PTR_FORMAT
#ifdef _LP64
#define G1PPRL_ADDR_BASE_H_FORMAT " %37s"
#else // _LP64
#define G1PPRL_ADDR_BASE_H_FORMAT " %21s"
#endif // _LP64
// For per-region info
#define G1PPRL_TYPE_FORMAT " %-4s"
#define G1PPRL_TYPE_H_FORMAT " %4s"
#define G1PPRL_BYTE_FORMAT " "SIZE_FORMAT_W(9)
#define G1PPRL_BYTE_H_FORMAT " %9s"
#define G1PPRL_DOUBLE_FORMAT " %14.1f"
#define G1PPRL_DOUBLE_H_FORMAT " %14s"
// For summary info
#define G1PPRL_SUM_ADDR_FORMAT(tag) " "tag":"G1PPRL_ADDR_BASE_FORMAT
#define G1PPRL_SUM_BYTE_FORMAT(tag) " "tag": "SIZE_FORMAT
#define G1PPRL_SUM_MB_FORMAT(tag) " "tag": %1.2f MB"
#define G1PPRL_SUM_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag)" / %1.2f %%"
G1PrintRegionLivenessInfoClosure::
G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name)
: _out(out),
_total_used_bytes(0), _total_capacity_bytes(0),
_total_prev_live_bytes(0), _total_next_live_bytes(0),
_hum_used_bytes(0), _hum_capacity_bytes(0),
_hum_prev_live_bytes(0), _hum_next_live_bytes(0) {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
MemRegion g1_committed = g1h->g1_committed();
MemRegion g1_reserved = g1h->g1_reserved();
double now = os::elapsedTime();
// Print the header of the output.
_out->cr();
_out->print_cr(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
_out->print_cr(G1PPRL_LINE_PREFIX" HEAP"
G1PPRL_SUM_ADDR_FORMAT("committed")
G1PPRL_SUM_ADDR_FORMAT("reserved")
G1PPRL_SUM_BYTE_FORMAT("region-size"),
g1_committed.start(), g1_committed.end(),
g1_reserved.start(), g1_reserved.end(),
HeapRegion::GrainBytes);
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_H_FORMAT
G1PPRL_ADDR_BASE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_BYTE_H_FORMAT
G1PPRL_DOUBLE_H_FORMAT,
"type", "address-range",
"used", "prev-live", "next-live", "gc-eff");
}
// It takes as a parameter a reference to one of the _hum_* fields, it
// deduces the corresponding value for a region in a humongous region
// series (either the region size, or what's left if the _hum_* field
// is < the region size), and updates the _hum_* field accordingly.
size_t G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* hum_bytes) {
size_t bytes = 0;
// The > 0 check is to deal with the prev and next live bytes which
// could be 0.
if (*hum_bytes > 0) {
bytes = MIN2((size_t) HeapRegion::GrainBytes, *hum_bytes);
*hum_bytes -= bytes;
}
return bytes;
}
// It deduces the values for a region in a humongous region series
// from the _hum_* fields and updates those accordingly. It assumes
// that that _hum_* fields have already been set up from the "starts
// humongous" region and we visit the regions in address order.
void G1PrintRegionLivenessInfoClosure::get_hum_bytes(size_t* used_bytes,
size_t* capacity_bytes,
size_t* prev_live_bytes,
size_t* next_live_bytes) {
assert(_hum_used_bytes > 0 && _hum_capacity_bytes > 0, "pre-condition");
*used_bytes = get_hum_bytes(&_hum_used_bytes);
*capacity_bytes = get_hum_bytes(&_hum_capacity_bytes);
*prev_live_bytes = get_hum_bytes(&_hum_prev_live_bytes);
*next_live_bytes = get_hum_bytes(&_hum_next_live_bytes);
}
bool G1PrintRegionLivenessInfoClosure::doHeapRegion(HeapRegion* r) {
const char* type = "";
HeapWord* bottom = r->bottom();
HeapWord* end = r->end();
size_t capacity_bytes = r->capacity();
size_t used_bytes = r->used();
size_t prev_live_bytes = r->live_bytes();
size_t next_live_bytes = r->next_live_bytes();
double gc_eff = r->gc_efficiency();
if (r->used() == 0) {
type = "FREE";
} else if (r->is_survivor()) {
type = "SURV";
} else if (r->is_young()) {
type = "EDEN";
} else if (r->startsHumongous()) {
type = "HUMS";
assert(_hum_used_bytes == 0 && _hum_capacity_bytes == 0 &&
_hum_prev_live_bytes == 0 && _hum_next_live_bytes == 0,
"they should have been zeroed after the last time we used them");
// Set up the _hum_* fields.
_hum_capacity_bytes = capacity_bytes;
_hum_used_bytes = used_bytes;
_hum_prev_live_bytes = prev_live_bytes;
_hum_next_live_bytes = next_live_bytes;
get_hum_bytes(&used_bytes, &capacity_bytes,
&prev_live_bytes, &next_live_bytes);
end = bottom + HeapRegion::GrainWords;
} else if (r->continuesHumongous()) {
type = "HUMC";
get_hum_bytes(&used_bytes, &capacity_bytes,
&prev_live_bytes, &next_live_bytes);
assert(end == bottom + HeapRegion::GrainWords, "invariant");
} else {
type = "OLD";
}
_total_used_bytes += used_bytes;
_total_capacity_bytes += capacity_bytes;
_total_prev_live_bytes += prev_live_bytes;
_total_next_live_bytes += next_live_bytes;
// Print a line for this particular region.
_out->print_cr(G1PPRL_LINE_PREFIX
G1PPRL_TYPE_FORMAT
G1PPRL_ADDR_BASE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_BYTE_FORMAT
G1PPRL_DOUBLE_FORMAT,
type, bottom, end,
used_bytes, prev_live_bytes, next_live_bytes, gc_eff);
return false;
}
G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() {
// Print the footer of the output.
_out->print_cr(G1PPRL_LINE_PREFIX);
_out->print_cr(G1PPRL_LINE_PREFIX
" SUMMARY"
G1PPRL_SUM_MB_FORMAT("capacity")
G1PPRL_SUM_MB_PERC_FORMAT("used")
G1PPRL_SUM_MB_PERC_FORMAT("prev-live")
G1PPRL_SUM_MB_PERC_FORMAT("next-live"),
bytes_to_mb(_total_capacity_bytes),
bytes_to_mb(_total_used_bytes),
perc(_total_used_bytes, _total_capacity_bytes),
bytes_to_mb(_total_prev_live_bytes),
perc(_total_prev_live_bytes, _total_capacity_bytes),
bytes_to_mb(_total_next_live_bytes),
perc(_total_next_live_bytes, _total_capacity_bytes));
_out->cr();
}