6668743: CMS: Consolidate block statistics reporting code

Reduce the amount of related code replication and improve pretty printing.

Reviewed-by: jmasa
This commit is contained in:
Y. Srinivas Ramakrishna 2008-02-29 14:42:56 -08:00
parent 51bf19209d
commit a6d8fca876
9 changed files with 130 additions and 133 deletions

@ -1071,85 +1071,56 @@ void BinaryTreeDictionary::reportStatistics() const {
// for each list in the tree. Also print some summary // for each list in the tree. Also print some summary
// information. // information.
class printTreeCensusClosure : public AscendTreeCensusClosure { class printTreeCensusClosure : public AscendTreeCensusClosure {
int _print_line;
size_t _totalFree; size_t _totalFree;
AllocationStats _totals; FreeList _total;
size_t _count;
public: public:
printTreeCensusClosure() { printTreeCensusClosure() {
_print_line = 0;
_totalFree = 0; _totalFree = 0;
_count = 0;
_totals.initialize();
} }
AllocationStats* totals() { return &_totals; } FreeList* total() { return &_total; }
size_t count() { return _count; }
void increment_count_by(size_t v) { _count += v; }
size_t totalFree() { return _totalFree; } size_t totalFree() { return _totalFree; }
void increment_totalFree_by(size_t v) { _totalFree += v; }
void do_list(FreeList* fl) { void do_list(FreeList* fl) {
bool nl = false; // "maybe this is not needed" isNearLargestChunk(fl->head()); if (++_print_line >= 40) {
FreeList::print_labels_on(gclog_or_tty, "size");
gclog_or_tty->print("%c %4d\t\t" "%7d\t" "%7d\t" _print_line = 0;
"%7d\t" "%7d\t" "%7d\t" "%7d\t" }
"%7d\t" "%7d\t" "%7d\t" fl->print_on(gclog_or_tty);
"%7d\t" "\n", _totalFree += fl->count() * fl->size() ;
" n"[nl], fl->size(), fl->bfrSurp(), fl->surplus(), total()->set_count( total()->count() + fl->count() );
fl->desired(), fl->prevSweep(), fl->beforeSweep(), fl->count(), total()->set_bfrSurp( total()->bfrSurp() + fl->bfrSurp() );
fl->coalBirths(), fl->coalDeaths(), fl->splitBirths(), total()->set_surplus( total()->splitDeaths() + fl->surplus() );
fl->splitDeaths()); total()->set_desired( total()->desired() + fl->desired() );
total()->set_prevSweep( total()->prevSweep() + fl->prevSweep() );
increment_totalFree_by(fl->count() * fl->size()); total()->set_beforeSweep(total()->beforeSweep() + fl->beforeSweep());
increment_count_by(fl->count()); total()->set_coalBirths( total()->coalBirths() + fl->coalBirths() );
totals()->set_bfrSurp(totals()->bfrSurp() + fl->bfrSurp()); total()->set_coalDeaths( total()->coalDeaths() + fl->coalDeaths() );
totals()->set_surplus(totals()->splitDeaths() + fl->surplus()); total()->set_splitBirths(total()->splitBirths() + fl->splitBirths());
totals()->set_prevSweep(totals()->prevSweep() + fl->prevSweep()); total()->set_splitDeaths(total()->splitDeaths() + fl->splitDeaths());
totals()->set_beforeSweep(totals()->beforeSweep() + fl->beforeSweep());
totals()->set_coalBirths(totals()->coalBirths() + fl->coalBirths());
totals()->set_coalDeaths(totals()->coalDeaths() + fl->coalDeaths());
totals()->set_splitBirths(totals()->splitBirths() + fl->splitBirths());
totals()->set_splitDeaths(totals()->splitDeaths() + fl->splitDeaths());
} }
}; };
void BinaryTreeDictionary::printDictCensus(void) const { void BinaryTreeDictionary::printDictCensus(void) const {
gclog_or_tty->print("\nBinaryTree\n"); gclog_or_tty->print("\nBinaryTree\n");
gclog_or_tty->print( FreeList::print_labels_on(gclog_or_tty, "size");
"%4s\t\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "\n",
"size", "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
printTreeCensusClosure ptc; printTreeCensusClosure ptc;
ptc.do_tree(root()); ptc.do_tree(root());
FreeList* total = ptc.total();
FreeList::print_labels_on(gclog_or_tty, " ");
total->print_on(gclog_or_tty, "TOTAL\t");
gclog_or_tty->print( gclog_or_tty->print(
"\t\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "totalFree(words): " SIZE_FORMAT_W(16)
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "\n", " growth: %8.5f deficit: %8.5f\n",
"bfrsurp", "surplus", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
gclog_or_tty->print(
"%s\t\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" "\n",
"totl",
ptc.totals()->bfrSurp(),
ptc.totals()->surplus(),
ptc.totals()->prevSweep(),
ptc.totals()->beforeSweep(),
ptc.count(),
ptc.totals()->coalBirths(),
ptc.totals()->coalDeaths(),
ptc.totals()->splitBirths(),
ptc.totals()->splitDeaths());
gclog_or_tty->print("totalFree(words): %7d growth: %8.5f deficit: %8.5f\n",
ptc.totalFree(), ptc.totalFree(),
(double)(ptc.totals()->splitBirths()+ptc.totals()->coalBirths() (double)(total->splitBirths() + total->coalBirths()
-ptc.totals()->splitDeaths()-ptc.totals()->coalDeaths()) - total->splitDeaths() - total->coalDeaths())
/(ptc.totals()->prevSweep() != 0 ? /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0),
(double)ptc.totals()->prevSweep() : 1.0), (double)(total->desired() - total->count())
(double)(ptc.totals()->desired() - ptc.count()) /(total->desired() != 0 ? (double)total->desired() : 1.0));
/(ptc.totals()->desired() != 0 ?
(double)ptc.totals()->desired() : 1.0));
} }
// Verify the following tree invariants: // Verify the following tree invariants:

@ -1835,7 +1835,7 @@ void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) {
guarantee(false, "NYI"); guarantee(false, "NYI");
} }
bool CompactibleFreeListSpace::linearAllocationWouldFail() { bool CompactibleFreeListSpace::linearAllocationWouldFail() const {
return _smallLinearAllocBlock._word_size == 0; return _smallLinearAllocBlock._word_size == 0;
} }
@ -1906,6 +1906,13 @@ CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
} }
} }
// Support for concurrent collection policy decisions.
bool CompactibleFreeListSpace::should_concurrent_collect() const {
// In the future we might want to add in frgamentation stats --
// including erosion of the "mountain" into this decision as well.
return !adaptive_freelists() && linearAllocationWouldFail();
}
// Support for compaction // Support for compaction
void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) { void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
@ -2013,11 +2020,11 @@ void CompactibleFreeListSpace::clearFLCensus() {
} }
} }
void CompactibleFreeListSpace::endSweepFLCensus(int sweepCt) { void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
setFLSurplus(); setFLSurplus();
setFLHints(); setFLHints();
if (PrintGC && PrintFLSCensus > 0) { if (PrintGC && PrintFLSCensus > 0) {
printFLCensus(sweepCt); printFLCensus(sweep_count);
} }
clearFLCensus(); clearFLCensus();
assert_locked(); assert_locked();
@ -2293,59 +2300,37 @@ void CompactibleFreeListSpace::checkFreeListConsistency() const {
} }
#endif #endif
void CompactibleFreeListSpace::printFLCensus(int sweepCt) const { void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
assert_lock_strong(&_freelistLock); assert_lock_strong(&_freelistLock);
ssize_t bfrSurp = 0; FreeList total;
ssize_t surplus = 0; gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
ssize_t desired = 0; FreeList::print_labels_on(gclog_or_tty, "size");
ssize_t prevSweep = 0;
ssize_t beforeSweep = 0;
ssize_t count = 0;
ssize_t coalBirths = 0;
ssize_t coalDeaths = 0;
ssize_t splitBirths = 0;
ssize_t splitDeaths = 0;
gclog_or_tty->print("end sweep# %d\n", sweepCt);
gclog_or_tty->print("%4s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "\n",
"size", "bfrsurp", "surplus", "desired", "prvSwep",
"bfrSwep", "count", "cBirths", "cDeaths", "sBirths",
"sDeaths");
size_t totalFree = 0; size_t totalFree = 0;
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
const FreeList *fl = &_indexedFreeList[i]; const FreeList *fl = &_indexedFreeList[i];
totalFree += fl->count() * fl->size(); totalFree += fl->count() * fl->size();
if (i % (40*IndexSetStride) == 0) {
gclog_or_tty->print("%4d\t" "%7d\t" "%7d\t" "%7d\t" FreeList::print_labels_on(gclog_or_tty, "size");
"%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "\n",
fl->size(), fl->bfrSurp(), fl->surplus(), fl->desired(),
fl->prevSweep(), fl->beforeSweep(), fl->count(), fl->coalBirths(),
fl->coalDeaths(), fl->splitBirths(), fl->splitDeaths());
bfrSurp += fl->bfrSurp();
surplus += fl->surplus();
desired += fl->desired();
prevSweep += fl->prevSweep();
beforeSweep += fl->beforeSweep();
count += fl->count();
coalBirths += fl->coalBirths();
coalDeaths += fl->coalDeaths();
splitBirths += fl->splitBirths();
splitDeaths += fl->splitDeaths();
} }
gclog_or_tty->print("%4s\t" fl->print_on(gclog_or_tty);
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() );
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" "\n", total.set_surplus( total.surplus() + fl->surplus() );
"totl", total.set_desired( total.desired() + fl->desired() );
bfrSurp, surplus, desired, prevSweep, beforeSweep, total.set_prevSweep( total.prevSweep() + fl->prevSweep() );
count, coalBirths, coalDeaths, splitBirths, splitDeaths); total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
gclog_or_tty->print_cr("Total free in indexed lists %d words", totalFree); total.set_count( total.count() + fl->count() );
total.set_coalBirths( total.coalBirths() + fl->coalBirths() );
total.set_coalDeaths( total.coalDeaths() + fl->coalDeaths() );
total.set_splitBirths(total.splitBirths() + fl->splitBirths());
total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
}
total.print_on(gclog_or_tty, "TOTAL");
gclog_or_tty->print_cr("Total free in indexed lists "
SIZE_FORMAT " words", totalFree);
gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n", gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n",
(double)(splitBirths+coalBirths-splitDeaths-coalDeaths)/ (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
(prevSweep != 0 ? (double)prevSweep : 1.0), (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
(double)(desired - count)/(desired != 0 ? (double)desired : 1.0)); (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
_dictionary->printDictCensus(); _dictionary->printDictCensus();
} }

@ -418,7 +418,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// chunk exists, return NULL. // chunk exists, return NULL.
FreeChunk* find_chunk_at_end(); FreeChunk* find_chunk_at_end();
bool adaptive_freelists() { return _adaptive_freelists; } bool adaptive_freelists() const { return _adaptive_freelists; }
void set_collector(CMSCollector* collector) { _collector = collector; } void set_collector(CMSCollector* collector) { _collector = collector; }
@ -566,7 +566,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
FreeChunk* allocateScratch(size_t size); FreeChunk* allocateScratch(size_t size);
// returns true if either the small or large linear allocation buffer is empty. // returns true if either the small or large linear allocation buffer is empty.
bool linearAllocationWouldFail(); bool linearAllocationWouldFail() const;
// Adjust the chunk for the minimum size. This version is called in // Adjust the chunk for the minimum size. This version is called in
// most cases in CompactibleFreeListSpace methods. // most cases in CompactibleFreeListSpace methods.
@ -585,6 +585,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size, void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size,
bool coalesced); bool coalesced);
// Support for decisions regarding concurrent collection policy
bool should_concurrent_collect() const;
// Support for compaction // Support for compaction
void prepare_for_compaction(CompactPoint* cp); void prepare_for_compaction(CompactPoint* cp);
void adjust_pointers(); void adjust_pointers();
@ -622,7 +625,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// coalescing of chunks during the sweep of garbage. // coalescing of chunks during the sweep of garbage.
// Print the statistics for the free lists. // Print the statistics for the free lists.
void printFLCensus(int sweepCt) const; void printFLCensus(size_t sweep_count) const;
// Statistics functions // Statistics functions
// Initialize census for lists before the sweep. // Initialize census for lists before the sweep.
@ -635,12 +638,11 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// Clear the census for each of the free lists. // Clear the census for each of the free lists.
void clearFLCensus(); void clearFLCensus();
// Perform functions for the census after the end of the sweep. // Perform functions for the census after the end of the sweep.
void endSweepFLCensus(int sweepCt); void endSweepFLCensus(size_t sweep_count);
// Return true if the count of free chunks is greater // Return true if the count of free chunks is greater
// than the desired number of free chunks. // than the desired number of free chunks.
bool coalOverPopulated(size_t size); bool coalOverPopulated(size_t size);
// Record (for each size): // Record (for each size):
// //
// split-births = #chunks added due to splits in (prev-sweep-end, // split-births = #chunks added due to splits in (prev-sweep-end,

@ -302,3 +302,29 @@ void FreeList::assert_proper_lock_protection_work() const {
#endif #endif
} }
#endif #endif
// Print the "label line" for free list stats.
void FreeList::print_labels_on(outputStream* st, const char* c) {
st->print("%16s\t", c);
st->print("%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t"
"%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t" "\n",
"bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
}
// Print the AllocationStats for the given free list. If the second argument
// to the call is a non-null string, it is printed in the first column;
// otherwise, if the argument is null (the default), then the size of the
// (free list) block is printed in the first column.
void FreeList::print_on(outputStream* st, const char* c) const {
if (c != NULL) {
st->print("%16s", c);
} else {
st->print(SIZE_FORMAT_W(16), size());
}
st->print("\t"
SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
bfrSurp(), surplus(), desired(), prevSweep(), beforeSweep(),
count(), coalBirths(), coalDeaths(), splitBirths(), splitDeaths());
}

@ -38,6 +38,7 @@ class Mutex;
class FreeList VALUE_OBJ_CLASS_SPEC { class FreeList VALUE_OBJ_CLASS_SPEC {
friend class CompactibleFreeListSpace; friend class CompactibleFreeListSpace;
friend class printTreeCensusClosure;
FreeChunk* _head; // List of free chunks FreeChunk* _head; // List of free chunks
FreeChunk* _tail; // Tail of list of free chunks FreeChunk* _tail; // Tail of list of free chunks
size_t _size; // Size in Heap words of each chunks size_t _size; // Size in Heap words of each chunks
@ -66,7 +67,8 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
void increment_count() { _count++; } void increment_count() { _count++; }
void decrement_count() { void decrement_count() {
_count--; _count--;
assert(_count >= 0, "Count should not be negative"); } assert(_count >= 0, "Count should not be negative");
}
public: public:
// Constructor // Constructor
@ -159,6 +161,10 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
ssize_t desired() const { ssize_t desired() const {
return _allocation_stats.desired(); return _allocation_stats.desired();
} }
void set_desired(ssize_t v) {
assert_proper_lock_protection();
_allocation_stats.set_desired(v);
}
void compute_desired(float inter_sweep_current, void compute_desired(float inter_sweep_current,
float inter_sweep_estimate) { float inter_sweep_estimate) {
assert_proper_lock_protection(); assert_proper_lock_protection();
@ -298,4 +304,8 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
// Verify that the chunk is in the list. // Verify that the chunk is in the list.
// found. Return NULL if "fc" is not found. // found. Return NULL if "fc" is not found.
bool verifyChunkInFreeLists(FreeChunk* fc) const; bool verifyChunkInFreeLists(FreeChunk* fc) const;
// Printing support
static void print_labels_on(outputStream* st, const char* c);
void print_on(outputStream* st, const char* c = NULL) const;
}; };

@ -24,6 +24,13 @@
// NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps! // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
allocationStats.cpp allocationStats.hpp
allocationStats.cpp ostream.hpp
allocationStats.hpp allocation.hpp
allocationStats.hpp gcUtil.hpp
allocationStats.hpp globalDefinitions.hpp
gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp
gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp

@ -98,6 +98,8 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC {
} }
ssize_t desired() const { return _desired; } ssize_t desired() const { return _desired; }
void set_desired(ssize_t v) { _desired = v; }
ssize_t coalDesired() const { return _coalDesired; } ssize_t coalDesired() const { return _coalDesired; }
void set_coalDesired(ssize_t v) { _coalDesired = v; } void set_coalDesired(ssize_t v) { _coalDesired = v; }

@ -148,12 +148,6 @@ allocation.hpp globals.hpp
allocation.inline.hpp os.hpp allocation.inline.hpp os.hpp
allocationStats.cpp allocationStats.hpp
allocationStats.hpp allocation.hpp
allocationStats.hpp gcUtil.hpp
allocationStats.hpp globalDefinitions.hpp
aprofiler.cpp aprofiler.hpp aprofiler.cpp aprofiler.hpp
aprofiler.cpp collectedHeap.inline.hpp aprofiler.cpp collectedHeap.inline.hpp
aprofiler.cpp oop.inline.hpp aprofiler.cpp oop.inline.hpp