diff options
-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. |