| Index: third_party/tcmalloc/chromium/src/central_freelist.cc
|
| diff --git a/third_party/tcmalloc/chromium/src/central_freelist.cc b/third_party/tcmalloc/chromium/src/central_freelist.cc
|
| index fff12600a7d040a7b7867ed28ff9d11763ff681d..0f8a5c07eb6baf36b503208225219c96d9a87a7e 100644
|
| --- a/third_party/tcmalloc/chromium/src/central_freelist.cc
|
| +++ b/third_party/tcmalloc/chromium/src/central_freelist.cc
|
| @@ -31,28 +31,51 @@
|
| // Author: Sanjay Ghemawat <opensource@google.com>
|
|
|
| #include "config.h"
|
| +#include <algorithm>
|
| #include "central_freelist.h"
|
| #include "free_list.h" // for FL_Next, FL_Push, etc
|
| #include "internal_logging.h" // for ASSERT, MESSAGE
|
| #include "page_heap.h" // for PageHeap
|
| #include "static_vars.h" // for Static
|
|
|
| +using std::min;
|
| +using std::max;
|
| +
|
| namespace tcmalloc {
|
|
|
| void CentralFreeList::Init(size_t cl) {
|
| size_class_ = cl;
|
| tcmalloc::DLL_Init(&empty_);
|
| tcmalloc::DLL_Init(&nonempty_);
|
| + num_spans_ = 0;
|
| counter_ = 0;
|
|
|
| + max_cache_size_ = kMaxNumTransferEntries;
|
| #ifdef TCMALLOC_SMALL_BUT_SLOW
|
| // Disable the transfer cache for the small footprint case.
|
| cache_size_ = 0;
|
| #else
|
| cache_size_ = 16;
|
| #endif
|
| + if (cl > 0) {
|
| + // Limit the maximum size of the cache based on the size class. If this
|
| + // is not done, large size class objects will consume a lot of memory if
|
| + // they just sit in the transfer cache.
|
| + int32_t bytes = Static::sizemap()->ByteSizeForClass(cl);
|
| + int32_t objs_to_move = Static::sizemap()->num_objects_to_move(cl);
|
| +
|
| + ASSERT(objs_to_move > 0 && bytes > 0);
|
| + // Limit each size class cache to at most 1MB of objects or one entry,
|
| + // whichever is greater. Total transfer cache memory used across all
|
| + // size classes then can't be greater than approximately
|
| + // 1MB * kMaxNumTransferEntries.
|
| + // min and max are in parens to avoid macro-expansion on windows.
|
| + max_cache_size_ = (min)(max_cache_size_,
|
| + (max)(1, (1024 * 1024) / (bytes * objs_to_move)));
|
| + cache_size_ = (min)(cache_size_, max_cache_size_);
|
| + }
|
| used_slots_ = 0;
|
| - ASSERT(cache_size_ <= kNumTransferEntries);
|
| + ASSERT(cache_size_ <= max_cache_size_);
|
| }
|
|
|
| void CentralFreeList::ReleaseListToSpans(void* start) {
|
| @@ -109,6 +132,7 @@ void CentralFreeList::ReleaseToSpans(void* object) {
|
| counter_ -= ((span->length<<kPageShift) /
|
| Static::sizemap()->ByteSizeForClass(span->sizeclass));
|
| tcmalloc::DLL_Remove(span);
|
| + --num_spans_;
|
|
|
| // Release central list lock while operating on pageheap
|
| lock_.Unlock();
|
| @@ -142,7 +166,7 @@ bool CentralFreeList::MakeCacheSpace() {
|
| // Is there room in the cache?
|
| if (used_slots_ < cache_size_) return true;
|
| // Check if we can expand this cache?
|
| - if (cache_size_ == kNumTransferEntries) return false;
|
| + if (cache_size_ == max_cache_size_) return false;
|
| // Ok, we'll try to grab an entry from some other size class.
|
| if (EvictRandomSizeClass(size_class_, false) ||
|
| EvictRandomSizeClass(size_class_, true)) {
|
| @@ -151,7 +175,7 @@ bool CentralFreeList::MakeCacheSpace() {
|
| // EvictRandomSizeClass (via ShrinkCache and the LockInverter), so the
|
| // cache_size may have changed. Therefore, check and verify that it is
|
| // still OK to increase the cache_size.
|
| - if (cache_size_ < kNumTransferEntries) {
|
| + if (cache_size_ < max_cache_size_) {
|
| cache_size_++;
|
| return true;
|
| }
|
| @@ -208,7 +232,7 @@ void CentralFreeList::InsertRange(void *start, void *end, int N) {
|
| MakeCacheSpace()) {
|
| int slot = used_slots_++;
|
| ASSERT(slot >=0);
|
| - ASSERT(slot < kNumTransferEntries);
|
| + ASSERT(slot < max_cache_size_);
|
| TCEntry *entry = &tc_slots_[slot];
|
| entry->head = start;
|
| entry->tail = end;
|
| @@ -292,7 +316,8 @@ void CentralFreeList::Populate() {
|
| if (span) Static::pageheap()->RegisterSizeClass(span, size_class_);
|
| }
|
| if (span == NULL) {
|
| - MESSAGE("tcmalloc: allocation failed", npages << kPageShift);
|
| + Log(kLog, __FILE__, __LINE__,
|
| + "tcmalloc: allocation failed", npages << kPageShift);
|
| lock_.Lock();
|
| return;
|
| }
|
| @@ -323,6 +348,7 @@ void CentralFreeList::Populate() {
|
| // Add span to list of non-empty spans
|
| lock_.Lock();
|
| tcmalloc::DLL_Prepend(&nonempty_, span);
|
| + ++num_spans_;
|
| counter_ += num;
|
| }
|
|
|
| @@ -331,4 +357,16 @@ int CentralFreeList::tc_length() {
|
| return used_slots_ * Static::sizemap()->num_objects_to_move(size_class_);
|
| }
|
|
|
| +size_t CentralFreeList::OverheadBytes() {
|
| + SpinLockHolder h(&lock_);
|
| + if (size_class_ == 0) { // 0 holds the 0-sized allocations
|
| + return 0;
|
| + }
|
| + const size_t pages_per_span = Static::sizemap()->class_to_pages(size_class_);
|
| + const size_t object_size = Static::sizemap()->class_to_size(size_class_);
|
| + ASSERT(object_size > 0);
|
| + const size_t overhead_per_span = (pages_per_span * kPageSize) % object_size;
|
| + return num_spans_ * overhead_per_span;
|
| +}
|
| +
|
| } // namespace tcmalloc
|
|
|