summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--third_party/tcmalloc/page_heap.cc24
-rw-r--r--third_party/tcmalloc/page_heap.h9
-rw-r--r--third_party/tcmalloc/tcmalloc.cc31
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.