[SERVER-28599] Test MarkThreadTemporarilyIdle with free list initialization Created: 03/Apr/17  Updated: 12/Apr/18  Resolved: 03/Nov/17

Status: Closed
Project: Core Server
Component/s: Internal Code
Affects Version/s: None
Fix Version/s: 3.6.0-rc3

Type: Improvement Priority: Major - P3
Reporter: Ramon Fernandez Marina Assignee: Mark Benvenuto
Resolution: Done Votes: 0
Labels: sysperf-36
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Backports
Depends
Related
is related to SERVER-31818 Add server parameter to disable MarkT... Closed
is related to SERVER-28249 Use TCMalloc MarkThreadTemporarilyIdl... Closed
Backwards Compatibility: Fully Compatible
Backport Requested:
v3.4
Sprint: Platforms 2017-08-21, Platforms 2017-09-11, Platforms 2017-10-02, Platforms 2017-10-23, Platforms 2017-11-13
Participants:
Linked BF Score: 0

 Description   

1
diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript
2
index 17335ef..5d163c7 100644
3
--- a/src/mongo/util/SConscript
4
+++ b/src/mongo/util/SConscript
5
@@ -249,6 +249,7 @@ if env['MONGO_ALLOCATOR'] == 'tcmalloc':
6
         tcmspEnv.Append(
7
             CPPDEFINES=[
8
                 'MONGO_HAVE_GPERFTOOLS_GET_THREAD_CACHE_SIZE',
9
+                'MONGO_HAVE_GPERFTOOLS_MARK_THREAD_TEMPORARILY_IDLE',
10
                 'MONGO_HAVE_GPERFTOOLS_SIZE_CLASS_STATS'
11
             ]
12
         )
13
diff --git a/src/mongo/util/tcmalloc_server_status_section.cpp b/src/mongo/util/tcmalloc_server_status_section.cpp
14
index cc2d672..8365ad0 100644
15
--- a/src/mongo/util/tcmalloc_server_status_section.cpp
16
+++ b/src/mongo/util/tcmalloc_server_status_section.cpp
17
@@ -79,8 +79,12 @@ void threadStateChange() {
18
     // terrible runaway if we're not careful.
19
     stdx::lock_guard<stdx::mutex> lk(tcmallocCleanupLock);
20
 #endif
21
+#if MONGO_HAVE_GPERFTOOLS_MARK_THREAD_TEMPORARILY_IDLE
22
+    MallocExtension::instance()->MarkThreadTemporarilyIdle();
23
+#else
24
     MallocExtension::instance()->MarkThreadIdle();
25
     MallocExtension::instance()->MarkThreadBusy();
26
+#endif
27
 }
28
 
29
 // Register threadStateChange callback
30
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
31
index 06138f8..fba567f 100644
32
--- a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h
33
+++ b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension.h
34
@@ -242,9 +242,16 @@ class PERFTOOLS_DLL_DECL MallocExtension {
35
   virtual void MarkThreadBusy();
36
 
37
   // Gets the size of this thread's cache in bytes.
38
-  // MONGODB ADDITION
39
+  // MONGODB ADDITIONS
40
   virtual size_t GetThreadCacheSize();
41
 
42
+  // Like MarkThreadIdle, but does not destroy the internal data
43
+  // structures of the thread cache. When the thread resumes, it wil
44
+  // have an empty cache but will not need to pay to reconstruct the
45
+  // cache data structures.
46
+  virtual void MarkThreadTemporarilyIdle();
47
+  // END MONGODB ADDITIONS
48
+ 
49
   // Gets the system allocator used by the malloc extension instance. Returns
50
   // NULL for malloc implementations that do not support pluggable system
51
   // allocators.
52
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
53
index 72a0a7c..5c64dae3 100644
54
--- a/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h
55
+++ b/src/third_party/gperftools-2.2/src/gperftools/malloc_extension_c.h
56
@@ -79,6 +79,8 @@ PERFTOOLS_DLL_DECL void MallocExtension_ReleaseToSystem(size_t num_bytes);
57
 PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory(void);
58
 PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size);
59
 PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(const void* p);
60
+PERFTOOLS_DLL_DECL size_t MallocExtension_GetThreadCacheSize(void);
61
+PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadTemporarilyIdle(void);
62
 
63
 /*
64
  * NOTE: These enum values MUST be kept in sync with the version in
65
diff --git a/src/third_party/gperftools-2.2/src/malloc_extension.cc b/src/third_party/gperftools-2.2/src/malloc_extension.cc
66
index 6fdb043..48872b8 100644
67
--- a/src/third_party/gperftools-2.2/src/malloc_extension.cc
68
+++ b/src/third_party/gperftools-2.2/src/malloc_extension.cc
69
@@ -198,6 +198,10 @@ void MallocExtension::GetFreeListSizes(
70
   v->clear();
71
 }
72
 
73
+void MallocExtension::MarkThreadTemporarilyIdle() {
74
+  // Default implementation does nothing
75
+}
76
+
77
 // The current malloc extension object.
78
 
79
 static MallocExtension* current_instance;
80
@@ -381,6 +385,8 @@ C_SHIM(ReleaseFreeMemory, void, (void), ());
81
 C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes));
82
 C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size));
83
 C_SHIM(GetAllocatedSize, size_t, (const void* p), (p));
84
+C_SHIM(GetThreadCacheSize, size_t, (void), ());
85
+C_SHIM(MarkThreadTemporarilyIdle, void, (void), ());
86
 
87
 // Can't use the shim here because of the need to translate the enums.
88
 extern "C"
89
diff --git a/src/third_party/gperftools-2.2/src/tcmalloc.cc b/src/third_party/gperftools-2.2/src/tcmalloc.cc
90
index 0bc8baa..e7d54c5 100644
91
--- a/src/third_party/gperftools-2.2/src/tcmalloc.cc
92
+++ b/src/third_party/gperftools-2.2/src/tcmalloc.cc
93
@@ -619,6 +619,10 @@ class TCMallocImplementation : public MallocExtension {
94
     return DumpHeapGrowthStackTraces();
95
   }
96
 
97
+  virtual void MarkThreadTemporarilyIdle() {
98
+    ThreadCache::BecomeTemporarilyIdle();
99
+  }
100
+
101
   virtual void Ranges(void* arg, RangeFunction func) {
102
     IterateOverRanges(arg, func);
103
   }
104
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
105
index 827609f..7e59e51 100644
106
--- a/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc
107
+++ b/src/third_party/gperftools-2.2/src/tests/markidle_unittest.cc
108
@@ -98,11 +98,28 @@ static void TestIdleUsage() {
109
   VLOG(0, "Post idle: %" PRIuS "\n", post_idle);
110
 }
111
 
112
+static void TestTemporarilyIdleUsage() {
113
+  const size_t original = MallocExtension::instance()->GetThreadCacheSize();
114
+
115
+  TestAllocation();
116
+  const size_t post_allocation = MallocExtension::instance()->GetThreadCacheSize();
117
+  CHECK_GT(post_allocation, original);
118
+
119
+  MallocExtension::instance()->MarkThreadIdle();
120
+  const size_t post_idle = MallocExtension::instance()->GetThreadCacheSize();
121
+  CHECK_EQ(post_idle, 0);
122
+
123
+  // Log after testing because logging can allocate heap memory.
124
+  VLOG(0, "Original usage: %" PRIuS "\n", original);
125
+  VLOG(0, "Post allocation: %" PRIuS "\n", post_allocation);
126
+  VLOG(0, "Post idle: %" PRIuS "\n", post_idle);
127
+}
128
+
129
 int main(int argc, char** argv) {
130
   RunThread(&TestIdleUsage);
131
   RunThread(&TestAllocation);
132
   RunThread(&MultipleIdleCalls);
133
-  RunThread(&MultipleIdleNonIdlePhases);
134
+  RunThread(&TestTemporarilyIdleUsage);
135
 
136
   printf("PASS\n");
137
   return 0;
138
diff --git a/src/third_party/gperftools-2.2/src/thread_cache.cc b/src/third_party/gperftools-2.2/src/thread_cache.cc
139
index b98fbee..7a8b8c0 100644
140
--- a/src/third_party/gperftools-2.2/src/thread_cache.cc
141
+++ b/src/third_party/gperftools-2.2/src/thread_cache.cc
142
@@ -437,6 +437,17 @@ void ThreadCache::BecomeIdle() {
143
   DeleteCache(heap);
144
 }
145
 
146
+void ThreadCache::BecomeTemporarilyIdle() {
147
+  ThreadCache* heap = GetCacheIfPresent();
148
+  if (heap) {
149
+    heap->Cleanup();
150
+    /* init state of free lists */
151
+    for (size_t cl = 0; cl < kNumClasses; ++cl) {
152
+      heap->list_[cl].Init();
153
+    }
154
+  }
155
+}
156
+
157
 void ThreadCache::DestroyThreadCache(void* ptr) {
158
   // Note that "ptr" cannot be NULL since pthread promises not
159
   // to invoke the destructor on NULL values, but for safety,
160
diff --git a/src/third_party/gperftools-2.2/src/thread_cache.h b/src/third_party/gperftools-2.2/src/thread_cache.h
161
index 5f0dc12..7d5c2dc 100644
162
--- a/src/third_party/gperftools-2.2/src/thread_cache.h
163
+++ b/src/third_party/gperftools-2.2/src/thread_cache.h
164
@@ -116,6 +116,7 @@ class ThreadCache {
165
   static ThreadCache* GetCacheWhichMustBePresent();
166
   static ThreadCache* CreateCacheIfNecessary();
167
   static void         BecomeIdle();
168
+  static void         BecomeTemporarilyIdle();
169
   static size_t       MinSizeForSlowPath();
170
   static void         SetMinSizeForSlowPath(size_t size);
171
 



 Comments   
Comment by Githook User [ 03/Nov/17 ]

Author:

{'name': 'Mark Benvenuto', 'username': 'markbenvenuto', 'email': 'mark.benvenuto@mongodb.com'}

Message: SERVER-28599 Fix MarkThreadTemporarilyIdle
Branch: master
https://github.com/mongodb/mongo/commit/4c6227e943d1867d0626624fc0975781e2b977ec

Generated at Thu Feb 08 04:18:34 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.