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

View File

@ -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:

View File

@ -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->print_on(gclog_or_tty);
fl->size(), fl->bfrSurp(), fl->surplus(), fl->desired(), total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() );
fl->prevSweep(), fl->beforeSweep(), fl->count(), fl->coalBirths(), total.set_surplus( total.surplus() + fl->surplus() );
fl->coalDeaths(), fl->splitBirths(), fl->splitDeaths()); total.set_desired( total.desired() + fl->desired() );
bfrSurp += fl->bfrSurp(); total.set_prevSweep( total.prevSweep() + fl->prevSweep() );
surplus += fl->surplus(); total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
desired += fl->desired(); total.set_count( total.count() + fl->count() );
prevSweep += fl->prevSweep(); total.set_coalBirths( total.coalBirths() + fl->coalBirths() );
beforeSweep += fl->beforeSweep(); total.set_coalDeaths( total.coalDeaths() + fl->coalDeaths() );
count += fl->count(); total.set_splitBirths(total.splitBirths() + fl->splitBirths());
coalBirths += fl->coalBirths(); total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
coalDeaths += fl->coalDeaths();
splitBirths += fl->splitBirths();
splitDeaths += fl->splitDeaths();
} }
gclog_or_tty->print("%4s\t" total.print_on(gclog_or_tty, "TOTAL");
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" gclog_or_tty->print_cr("Total free in indexed lists "
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" "\n", SIZE_FORMAT " words", totalFree);
"totl",
bfrSurp, surplus, desired, prevSweep, beforeSweep,
count, coalBirths, coalDeaths, splitBirths, splitDeaths);
gclog_or_tty->print_cr("Total free in indexed lists %d 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();
} }

View File

@ -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,

View File

@ -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());
}

View File

@ -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
@ -63,10 +64,11 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
protected: protected:
void init_statistics(); void init_statistics();
void set_count(ssize_t v) { _count = v;} void set_count(ssize_t v) { _count = v;}
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;
}; };

View File

@ -24,10 +24,17 @@
// 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!
gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp allocationStats.cpp allocationStats.hpp
gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp allocationStats.cpp ostream.hpp
gcAdaptivePolicyCounters.cpp resourceArea.hpp allocationStats.hpp allocation.hpp
allocationStats.hpp gcUtil.hpp
allocationStats.hpp globalDefinitions.hpp
gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp
gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp
gcAdaptivePolicyCounters.cpp resourceArea.hpp
gcAdaptivePolicyCounters.cpp gcAdaptivePolicyCounters.hpp gcAdaptivePolicyCounters.cpp gcAdaptivePolicyCounters.hpp
gSpaceCounters.cpp generation.hpp gSpaceCounters.cpp generation.hpp
@ -44,7 +51,7 @@ immutableSpace.cpp universe.hpp
isGCActiveMark.hpp parallelScavengeHeap.hpp isGCActiveMark.hpp parallelScavengeHeap.hpp
markSweep.inline.hpp psParallelCompact.hpp markSweep.inline.hpp psParallelCompact.hpp
mutableNUMASpace.cpp mutableNUMASpace.hpp mutableNUMASpace.cpp mutableNUMASpace.hpp
mutableNUMASpace.cpp sharedHeap.hpp mutableNUMASpace.cpp sharedHeap.hpp

View File

@ -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; }

View File

@ -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
@ -1935,7 +1929,7 @@ icache_<arch>.hpp generate_platform_dependent_include
init.cpp bytecodes.hpp init.cpp bytecodes.hpp
init.cpp collectedHeap.hpp init.cpp collectedHeap.hpp
init.cpp handles.inline.hpp init.cpp handles.inline.hpp
init.cpp icBuffer.hpp init.cpp icBuffer.hpp
init.cpp icache.hpp init.cpp icache.hpp
init.cpp init.hpp init.cpp init.hpp