-
Type: Improvement
-
Resolution: Done
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Internal Code
-
Fully Compatible
-
v3.4
-
Platforms 2017-08-21, Platforms 2017-09-11, Platforms 2017-10-02, Platforms 2017-10-23, Platforms 2017-11-13
-
0
Unable to find source-code formatter for language: diff. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index 17335ef..5d163c7 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -249,6 +249,7 @@ if env['MONGO_ALLOCATOR'] == 'tcmalloc': tcmspEnv.Append( CPPDEFINES=[ 'MONGO_HAVE_GPERFTOOLS_GET_THREAD_CACHE_SIZE', + 'MONGO_HAVE_GPERFTOOLS_MARK_THREAD_TEMPORARILY_IDLE', 'MONGO_HAVE_GPERFTOOLS_SIZE_CLASS_STATS' ] ) diff --git a/src/mongo/util/tcmalloc_server_status_section.cpp b/src/mongo/util/tcmalloc_server_status_section.cpp index cc2d672..8365ad0 100644 --- a/src/mongo/util/tcmalloc_server_status_section.cpp +++ b/src/mongo/util/tcmalloc_server_status_section.cpp @@ -79,8 +79,12 @@ void threadStateChange() { // terrible runaway if we're not careful. stdx::lock_guard<stdx::mutex> lk(tcmallocCleanupLock); #endif +#if MONGO_HAVE_GPERFTOOLS_MARK_THREAD_TEMPORARILY_IDLE + MallocExtension::instance()->MarkThreadTemporarilyIdle(); +#else MallocExtension::instance()->MarkThreadIdle(); MallocExtension::instance()->MarkThreadBusy(); +#endif } // Register threadStateChange callback diff --git a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h index 06138f8..fba567f 100644 --- a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h +++ b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h @@ -242,9 +242,16 @@ class PERFTOOLS_DLL_DECL MallocExtension { virtual void MarkThreadBusy(); // Gets the size of this thread's cache in bytes. - // MONGODB ADDITION + // MONGODB ADDITIONS virtual size_t GetThreadCacheSize(); + // Like MarkThreadIdle, but does not destroy the internal data + // structures of the thread cache. When the thread resumes, it wil + // have an empty cache but will not need to pay to reconstruct the + // cache data structures. + virtual void MarkThreadTemporarilyIdle(); + // END MONGODB ADDITIONS + // Gets the system allocator used by the malloc extension instance. Returns // NULL for malloc implementations that do not support pluggable system // allocators. diff --git a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h index 72a0a7c..5c64dae3 100644 --- a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h +++ b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h @@ -79,6 +79,8 @@ PERFTOOLS_DLL_DECL void MallocExtension_ReleaseToSystem(size_t num_bytes); PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory(void); PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size); PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(const void* p); +PERFTOOLS_DLL_DECL size_t MallocExtension_GetThreadCacheSize(void); +PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadTemporarilyIdle(void); /* * NOTE: These enum values MUST be kept in sync with the version in diff --git a/src/third_party/gperftools-2.2/src/malloc_extension.cc b/src/third_party/gperftools-2.2/src/malloc_extension.cc index 6fdb043..48872b8 100644 --- a/src/third_party/gperftools-2.2/src/malloc_extension.cc +++ b/src/third_party/gperftools-2.2/src/malloc_extension.cc @@ -198,6 +198,10 @@ void MallocExtension::GetFreeListSizes( v->clear(); } +void MallocExtension::MarkThreadTemporarilyIdle() { + // Default implementation does nothing +} + // The current malloc extension object. static MallocExtension* current_instance; @@ -381,6 +385,8 @@ C_SHIM(ReleaseFreeMemory, void, (void), ()); C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); C_SHIM(GetAllocatedSize, size_t, (const void* p), (p)); +C_SHIM(GetThreadCacheSize, size_t, (void), ()); +C_SHIM(MarkThreadTemporarilyIdle, void, (void), ()); // Can't use the shim here because of the need to translate the enums. extern "C" diff --git a/src/third_party/gperftools-2.2/src/tcmalloc.cc b/src/third_party/gperftools-2.2/src/tcmalloc.cc index 0bc8baa..e7d54c5 100644 --- a/src/third_party/gperftools-2.2/src/tcmalloc.cc +++ b/src/third_party/gperftools-2.2/src/tcmalloc.cc @@ -619,6 +619,10 @@ class TCMallocImplementation : public MallocExtension { return DumpHeapGrowthStackTraces(); } + virtual void MarkThreadTemporarilyIdle() { + ThreadCache::BecomeTemporarilyIdle(); + } + virtual void Ranges(void* arg, RangeFunction func) { IterateOverRanges(arg, func); } diff --git a/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc b/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc index 827609f..7e59e51 100644 --- a/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc +++ b/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc @@ -98,11 +98,28 @@ static void TestIdleUsage() { VLOG(0, "Post idle: %" PRIuS "\n", post_idle); } +static void TestTemporarilyIdleUsage() { + const size_t original = MallocExtension::instance()->GetThreadCacheSize(); + + TestAllocation(); + const size_t post_allocation = MallocExtension::instance()->GetThreadCacheSize(); + CHECK_GT(post_allocation, original); + + MallocExtension::instance()->MarkThreadIdle(); + const size_t post_idle = MallocExtension::instance()->GetThreadCacheSize(); + CHECK_EQ(post_idle, 0); + + // Log after testing because logging can allocate heap memory. + VLOG(0, "Original usage: %" PRIuS "\n", original); + VLOG(0, "Post allocation: %" PRIuS "\n", post_allocation); + VLOG(0, "Post idle: %" PRIuS "\n", post_idle); +} + int main(int argc, char** argv) { RunThread(&TestIdleUsage); RunThread(&TestAllocation); RunThread(&MultipleIdleCalls); - RunThread(&MultipleIdleNonIdlePhases); + RunThread(&TestTemporarilyIdleUsage); printf("PASS\n"); return 0; diff --git a/src/third_party/gperftools-2.2/src/thread_cache.cc b/src/third_party/gperftools-2.2/src/thread_cache.cc index b98fbee..7a8b8c0 100644 --- a/src/third_party/gperftools-2.2/src/thread_cache.cc +++ b/src/third_party/gperftools-2.2/src/thread_cache.cc @@ -437,6 +437,17 @@ void ThreadCache::BecomeIdle() { DeleteCache(heap); } +void ThreadCache::BecomeTemporarilyIdle() { + ThreadCache* heap = GetCacheIfPresent(); + if (heap) { + heap->Cleanup(); + /* init state of free lists */ + for (size_t cl = 0; cl < kNumClasses; ++cl) { + heap->list_[cl].Init(); + } + } +} + void ThreadCache::DestroyThreadCache(void* ptr) { // Note that "ptr" cannot be NULL since pthread promises not // to invoke the destructor on NULL values, but for safety, diff --git a/src/third_party/gperftools-2.2/src/thread_cache.h b/src/third_party/gperftools-2.2/src/thread_cache.h index 5f0dc12..7d5c2dc 100644 --- a/src/third_party/gperftools-2.2/src/thread_cache.h +++ b/src/third_party/gperftools-2.2/src/thread_cache.h @@ -116,6 +116,7 @@ class ThreadCache { static ThreadCache* GetCacheWhichMustBePresent(); static ThreadCache* CreateCacheIfNecessary(); static void BecomeIdle(); + static void BecomeTemporarilyIdle(); static size_t MinSizeForSlowPath(); static void SetMinSizeForSlowPath(size_t size);
- is related to
-
SERVER-31818 Add server parameter to disable MarkThread{temporary}Idle
- Closed
-
SERVER-28249 Use TCMalloc MarkThreadTemporarilyIdle instead of MarkThreadIdle
- Closed