diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-06 18:33:31 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-06 18:33:31 +0000 |
commit | 9c92338c5f8770c440799d24387c3733fd6d826b (patch) | |
tree | 271f123e2ae934a45dc6fef91db6d4abe327d2dd | |
parent | a97063189b7596ec805dab89f0d2fa7222c63191 (diff) | |
download | chromium_src-9c92338c5f8770c440799d24387c3733fd6d826b.zip chromium_src-9c92338c5f8770c440799d24387c3733fd6d826b.tar.gz chromium_src-9c92338c5f8770c440799d24387c3733fd6d826b.tar.bz2 |
Tracks the amount of committed vs uncommitted memory in tcmalloc's page heap's freelists
Keeps track of the number of reserved but not committed pages in the freelist and uses that to calculate a waste metric, which is the ratio of committed pages vs pages used by the application. This is exposed in the GetStats() call (which is used for about:tcmalloc) and through GetNumericalProperty() in MallocExtension.
BUG=none
TEST=open about:tcmalloc and monitor 'WASTE' columns while using the browser
Review URL: http://codereview.chromium.org/251065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28133 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | third_party/tcmalloc/page_heap.cc | 24 | ||||
-rw-r--r-- | third_party/tcmalloc/page_heap.h | 9 | ||||
-rw-r--r-- | third_party/tcmalloc/tcmalloc.cc | 31 |
3 files changed, 53 insertions, 11 deletions
diff --git a/third_party/tcmalloc/page_heap.cc b/third_party/tcmalloc/page_heap.cc index b46e728..f92cfc4 100644 --- a/third_party/tcmalloc/page_heap.cc +++ b/third_party/tcmalloc/page_heap.cc @@ -51,6 +51,7 @@ PageHeap::PageHeap() pagemap_cache_(0), free_pages_(0), system_bytes_(0), + committed_bytes_(0), scavenge_counter_(0), // Start scavenging at kMaxPages list scavenge_index_(kMaxPages-1) { @@ -153,11 +154,13 @@ Span* PageHeap::Split(Span* span, Length n) { void PageHeap::CommitSpan(Span* span) { TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift), static_cast<size_t>(span->length << kPageShift)); + committed_bytes_ += span->length << kPageShift; } void PageHeap::DecommitSpan(Span* span) { TCMalloc_SystemRelease(reinterpret_cast<void*>(span->start << kPageShift), static_cast<size_t>(span->length << kPageShift)); + committed_bytes_ -= span->length << kPageShift; } Span* PageHeap::Carve(Span* span, Length n) { @@ -233,6 +236,14 @@ void PageHeap::Delete(Span* span) { // Merge preceding span into this span ASSERT(prev->start + prev->length == p); const Length len = prev->length; + if (prev->location == Span::ON_RETURNED_FREELIST) { + // We're about to put the merge span into the returned freelist and call + // DecommitSpan() on it, which will mark the entire span including this + // one as released and decrease committed_bytes_ by the size of the + // merged span. To make the math work out we temporarily increase the + // committed_bytes_ amount. + committed_bytes_ += prev->length << kPageShift; + } DLL_Remove(prev); DeleteSpan(prev); span->start -= len; @@ -245,6 +256,10 @@ void PageHeap::Delete(Span* span) { // Merge next span into this span ASSERT(next->start == p+n); const Length len = next->length; + if (next->location == Span::ON_RETURNED_FREELIST) { + // See the comment below 'if (prev->location ...' for explanation. + committed_bytes_ += next->length << kPageShift; + } DLL_Remove(next); DeleteSpan(next); span->length += len; @@ -299,8 +314,7 @@ void PageHeap::IncrementalScavenge(Length n) { Span* s = slist->normal.prev; ASSERT(s->location == Span::ON_NORMAL_FREELIST); DLL_Remove(s); - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); + DecommitSpan(s); s->location = Span::ON_RETURNED_FREELIST; DLL_Prepend(&slist->returned, s); @@ -430,6 +444,7 @@ bool PageHeap::GrowHeap(Length n) { uint64_t old_system_bytes = system_bytes_; system_bytes_ += (ask << kPageShift); + committed_bytes_ += (ask << kPageShift); const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; ASSERT(p > 0); @@ -491,7 +506,7 @@ bool PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, return true; } -static void ReleaseFreeList(Span* list, Span* returned) { +void PageHeap::ReleaseFreeList(Span* list, Span* returned) { // Walk backwards through list so that when we push these // spans on the "returned" list, we preserve the order. while (!DLL_IsEmpty(list)) { @@ -500,8 +515,7 @@ static void ReleaseFreeList(Span* list, Span* returned) { DLL_Prepend(returned, s); ASSERT(s->location == Span::ON_NORMAL_FREELIST); s->location = Span::ON_RETURNED_FREELIST; - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); + DecommitSpan(s); } } diff --git a/third_party/tcmalloc/page_heap.h b/third_party/tcmalloc/page_heap.h index aec933d..100cae4 100644 --- a/third_party/tcmalloc/page_heap.h +++ b/third_party/tcmalloc/page_heap.h @@ -121,6 +121,8 @@ class PageHeap { // Return number of bytes allocated from system inline uint64_t SystemBytes() const { return system_bytes_; } + inline uint64_t CommittedBytes() const { return committed_bytes_; } + // Return number of free bytes in heap uint64_t FreeBytes() const { return (static_cast<uint64_t>(free_pages_) << kPageShift); @@ -188,6 +190,9 @@ class PageHeap { // Bytes allocated from system uint64_t system_bytes_; + // Bytes committed, always <= system_bytes_. + uint64_t committed_bytes_; + bool GrowHeap(Length n); // REQUIRES: span->length >= n @@ -220,6 +225,10 @@ class PageHeap { // IncrementalScavenge(n) is called whenever n pages are freed. void IncrementalScavenge(Length n); + // Releases all memory held in the given list's 'normal' freelist and adds + // it to the 'released' freelist. + void ReleaseFreeList(Span* list, Span* returned); + // Number of pages to deallocate before doing more scavenging int64_t scavenge_counter_; diff --git a/third_party/tcmalloc/tcmalloc.cc b/third_party/tcmalloc/tcmalloc.cc index e3bbb81..97cc414 100644 --- a/third_party/tcmalloc/tcmalloc.cc +++ b/third_party/tcmalloc/tcmalloc.cc @@ -367,6 +367,7 @@ size_t InvalidGetAllocatedSize(void* ptr) { // Extract interesting stats struct TCMallocStats { uint64_t system_bytes; // Bytes alloced from system + uint64_t committed_bytes; // Bytes alloced and committed from system uint64_t thread_bytes; // Bytes in thread caches uint64_t central_bytes; // Bytes in central cache uint64_t transfer_bytes; // Bytes in central transfer cache @@ -398,6 +399,7 @@ static void ExtractStats(TCMallocStats* r, uint64_t* class_count) { { //scope SpinLockHolder h(Static::pageheap_lock()); r->system_bytes = Static::pageheap()->SystemBytes(); + r->committed_bytes = Static::pageheap()->CommittedBytes(); r->metadata_bytes = tcmalloc::metadata_system_bytes(); r->pageheap_bytes = Static::pageheap()->FreeBytes(); } @@ -411,6 +413,20 @@ static void DumpStats(TCMalloc_Printer* out, int level) { static const double MB = 1048576.0; + const uint64_t bytes_in_use = stats.system_bytes + - stats.pageheap_bytes + - stats.central_bytes + - stats.transfer_bytes + - stats.thread_bytes; + + out->printf("WASTE: %7.1f MB committed but not used\n" + "WASTE: %7.1f MB bytes committed, %7.1f MB bytes in use\n" + "WASTE: committed/used ratio of %f\n", + (stats.committed_bytes - bytes_in_use) / MB, + stats.committed_bytes / MB, + bytes_in_use / MB, + stats.committed_bytes / static_cast<double>(bytes_in_use)); + if (level >= 2) { out->printf("------------------------------------------------\n"); uint64_t cumulative = 0; @@ -435,14 +451,9 @@ static void DumpStats(TCMalloc_Printer* out, int level) { DumpSystemAllocatorStats(out); } - const uint64_t bytes_in_use = stats.system_bytes - - stats.pageheap_bytes - - stats.central_bytes - - stats.transfer_bytes - - stats.thread_bytes; - out->printf("------------------------------------------------\n" "MALLOC: %12" PRIu64 " (%7.1f MB) Heap size\n" + "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes committed\n" "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes in use by application\n" "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in page heap\n" "MALLOC: %12" PRIu64 " (%7.1f MB) Bytes free in central cache\n" @@ -453,6 +464,7 @@ static void DumpStats(TCMalloc_Printer* out, int level) { "MALLOC: %12" PRIu64 " (%7.1f MB) Metadata allocated\n" "------------------------------------------------\n", stats.system_bytes, stats.system_bytes / MB, + stats.committed_bytes, stats.committed_bytes / MB, bytes_in_use, bytes_in_use / MB, stats.pageheap_bytes, stats.pageheap_bytes / MB, stats.central_bytes, stats.central_bytes / MB, @@ -571,6 +583,13 @@ class TCMallocImplementation : public MallocExtension { return true; } + if (strcmp(name, "generic.committed_bytes") == 0) { + TCMallocStats stats; + ExtractStats(&stats, NULL); + *value = Static::pageheap()->CommittedBytes(); + return true; + } + if (strcmp(name, "tcmalloc.slack_bytes") == 0) { // We assume that bytes in the page heap are not fragmented too // badly, and are therefore available for allocation. |