MallocBench should scavenge explicitly instead of waiting
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Apr 2014 03:52:39 +0000 (03:52 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Apr 2014 03:52:39 +0000 (03:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=131661

Reviewed by Andreas Kling.

PerformanceTests:
* MallocBench/MallocBench.xcodeproj/project.pbxproj: Don't build mbmalloc
by default because it will overwrite any other mbmalloc you're working
with in the WebKitBuild directory.

* MallocBench/MallocBench/Benchmark.cpp:
(Benchmark::run): Scavenge explicitly instead of waiting. This is faster,
and it's the only way to get FastMalloc to scavenge. (That's a bug in
FastMalloc, but we don't want it to interfere with broader testing.)

* MallocBench/MallocBench/mbmalloc.cpp:
* MallocBench/MallocBench/mbmalloc.h: Added a scavenge implementation
for system malloc.

Source/bmalloc:
Added explicit scavenge support to bmalloc. This isn't a memory win,
since bmalloc's per-thread cache is so small. But it makes testing
simpler.

* bmalloc/Allocator.cpp:
(bmalloc::Allocator::~Allocator):
(bmalloc::Allocator::scavenge):
* bmalloc/Allocator.h:
* bmalloc/Cache.cpp:
(bmalloc::Cache::operator new):
(bmalloc::Cache::operator delete):
(bmalloc::Cache::Cache):
(bmalloc::Cache::scavenge):
* bmalloc/Cache.h:
* bmalloc/Deallocator.cpp:
(bmalloc::Deallocator::~Deallocator):
(bmalloc::Deallocator::scavenge):
* bmalloc/Deallocator.h: Factored existing scavenging code into helper
functions, for reuse.

* bmalloc/Heap.cpp:
(bmalloc::sleep):
(bmalloc::Heap::concurrentScavenge):
(bmalloc::Heap::scavenge):
(bmalloc::Heap::scavengeSmallPages):
(bmalloc::Heap::scavengeMediumPages):
(bmalloc::Heap::scavengeLargeRanges):
* bmalloc/Heap.h: Made scavenge sleep duration a parameter. Forced
scavenging -- in response to a benchmark or a low memory warning --
wants to complete as soon as possible, so its sleep duration is 0.

* bmalloc/bmalloc.h:
(bmalloc::api::scavenge):
* bmalloc/mbmalloc.cpp: Exported the scavenge API for MallocBench's use.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@167292 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
PerformanceTests/ChangeLog
PerformanceTests/MallocBench/MallocBench.xcodeproj/project.pbxproj
PerformanceTests/MallocBench/MallocBench/Benchmark.cpp
PerformanceTests/MallocBench/MallocBench/mbmalloc.cpp
PerformanceTests/MallocBench/MallocBench/mbmalloc.h
Source/bmalloc/ChangeLog
Source/bmalloc/bmalloc/Allocator.cpp
Source/bmalloc/bmalloc/Allocator.h
Source/bmalloc/bmalloc/Cache.cpp
Source/bmalloc/bmalloc/Cache.h
Source/bmalloc/bmalloc/Deallocator.cpp
Source/bmalloc/bmalloc/Deallocator.h
Source/bmalloc/bmalloc/Heap.cpp
Source/bmalloc/bmalloc/Heap.h
Source/bmalloc/bmalloc/bmalloc.h
Source/bmalloc/bmalloc/mbmalloc.cpp

index 1effdf865bd45d96e67505d7f493e7fdbf2fc937..8c070299976b0ba7a804c01abb11785cb5a45177 100644 (file)
@@ -1,3 +1,23 @@
+2014-04-14  Geoffrey Garen  <ggaren@apple.com>
+
+        MallocBench should scavenge explicitly instead of waiting
+        https://bugs.webkit.org/show_bug.cgi?id=131661
+
+        Reviewed by Andreas Kling.
+
+        * MallocBench/MallocBench.xcodeproj/project.pbxproj: Don't build mbmalloc
+        by default because it will overwrite any other mbmalloc you're working
+        with in the WebKitBuild directory.
+
+        * MallocBench/MallocBench/Benchmark.cpp:
+        (Benchmark::run): Scavenge explicitly instead of waiting. This is faster,
+        and it's the only way to get FastMalloc to scavenge. (That's a bug in
+        FastMalloc, but we don't want it to interfere with broader testing.)
+
+        * MallocBench/MallocBench/mbmalloc.cpp:
+        * MallocBench/MallocBench/mbmalloc.h: Added a scavenge implementation
+        for system malloc.
+
 2014-04-14  Geoffrey Garen  <ggaren@apple.com>
 
         A few MallocBench record/replay fixes
index c394842e873dbf787914d7c3a7abc645c9d040bd..6f6633f5547459909145dedc1318a5737489a11d 100644 (file)
                14E11932177ECC8B003A8D15 /* CPUCount.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14E11930177ECC8B003A8D15 /* CPUCount.cpp */; };
 /* End PBXBuildFile section */
 
-/* Begin PBXContainerItemProxy section */
-               14CC393D18EA813F004AFE34 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 14452CA1177D24460097E057 /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = 14CC393718EA811F004AFE34;
-                       remoteInfo = mbmalloc;
-               };
-/* End PBXContainerItemProxy section */
-
 /* Begin PBXCopyFilesBuildPhase section */
                14452CA7177D24460097E057 /* Copy Files */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildRules = (
                        );
                        dependencies = (
-                               14CC393E18EA813F004AFE34 /* PBXTargetDependency */,
                        );
                        name = MallocBench;
                        productName = MallocBench;
                };
 /* End PBXSourcesBuildPhase section */
 
-/* Begin PBXTargetDependency section */
-               14CC393E18EA813F004AFE34 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = 14CC393718EA811F004AFE34 /* mbmalloc */;
-                       targetProxy = 14CC393D18EA813F004AFE34 /* PBXContainerItemProxy */;
-               };
-/* End PBXTargetDependency section */
-
 /* Begin XCBuildConfiguration section */
                14452CB5177D24460097E057 /* Debug */ = {
                        isa = XCBuildConfiguration;
index b02f113487a9e068ec82b867c70b99beebae3fe7..a873611c65095aa90909fd3e9a782f1965beb774 100644 (file)
@@ -184,14 +184,8 @@ void Benchmark::run()
     
     if (!m_measureHeap)
         return;
-
-    // Wait a bit for any async freeing to finish.
-    size_t last;
-    do {
-        last = currentMemoryBytes().resident;
-        std::this_thread::sleep_for(std::chrono::seconds(2));
-    } while (currentMemoryBytes().resident < last);
-
+    
+    mbscavenge();
     m_memory = currentMemoryBytes();
 }
 
index 1f40c5ddeb77b8379cee8e069d9163bff001e040..546a886ec1f7728ecdd89b6e0b82ed6238391bf1 100644 (file)
@@ -26,6 +26,7 @@
 #include <limits>
 #include <stdio.h>
 #include <stdlib.h>
+#import <malloc/malloc.h>
 
 extern "C" {
 
@@ -44,4 +45,9 @@ void* mbrealloc(void* p, size_t, size_t newSize)
     return realloc(p, newSize);
 }
 
+void mbscavenge()
+{
+    malloc_zone_pressure_relief(nullptr, 0);
+}
+
 } // extern "C"
index 7a0db282181f4630cce9bc29359b9cfe91758b43..cc77347d0712181593309bccc62e03198115b28f 100644 (file)
@@ -37,7 +37,8 @@ extern "C" {
 void* mbmalloc(size_t);
 void mbfree(void*, size_t);
 void* mbrealloc(void*, size_t, size_t);
-
+void mbscavenge();
+    
 }
 
 // Catch accidental benchmark allocation through malloc and free. All benchmark
index 23fbd55e8ae70ac52079adbc2ae09c8889cb62db..de312207f8992ba35e3a94571d1cec0c6b3d74ea 100644 (file)
@@ -1,3 +1,45 @@
+2014-04-14  Geoffrey Garen  <ggaren@apple.com>
+
+        MallocBench should scavenge explicitly instead of waiting
+        https://bugs.webkit.org/show_bug.cgi?id=131661
+
+        Reviewed by Andreas Kling.
+
+        Added explicit scavenge support to bmalloc. This isn't a memory win,
+        since bmalloc's per-thread cache is so small. But it makes testing
+        simpler.
+
+        * bmalloc/Allocator.cpp:
+        (bmalloc::Allocator::~Allocator):
+        (bmalloc::Allocator::scavenge):
+        * bmalloc/Allocator.h:
+        * bmalloc/Cache.cpp:
+        (bmalloc::Cache::operator new):
+        (bmalloc::Cache::operator delete):
+        (bmalloc::Cache::Cache):
+        (bmalloc::Cache::scavenge):
+        * bmalloc/Cache.h:
+        * bmalloc/Deallocator.cpp:
+        (bmalloc::Deallocator::~Deallocator):
+        (bmalloc::Deallocator::scavenge):
+        * bmalloc/Deallocator.h: Factored existing scavenging code into helper
+        functions, for reuse.
+
+        * bmalloc/Heap.cpp:
+        (bmalloc::sleep):
+        (bmalloc::Heap::concurrentScavenge):
+        (bmalloc::Heap::scavenge):
+        (bmalloc::Heap::scavengeSmallPages):
+        (bmalloc::Heap::scavengeMediumPages):
+        (bmalloc::Heap::scavengeLargeRanges):
+        * bmalloc/Heap.h: Made scavenge sleep duration a parameter. Forced
+        scavenging -- in response to a benchmark or a low memory warning --
+        wants to complete as soon as possible, so its sleep duration is 0.
+
+        * bmalloc/bmalloc.h:
+        (bmalloc::api::scavenge):
+        * bmalloc/mbmalloc.cpp: Exported the scavenge API for MallocBench's use.
+
 2014-04-14  Geoffrey Garen  <ggaren@apple.com>
 
         Use 4kB pages on Mac
index 59d5cf8c4b344e39d3f373e1781041d826b6ebb1..843376356bbab569d385ec0fb086477da864b8b7 100644 (file)
@@ -50,6 +50,11 @@ Allocator::Allocator(Deallocator& deallocator)
 }
 
 Allocator::~Allocator()
+{
+    scavenge();
+}
+    
+void Allocator::scavenge()
 {
     for (auto& allocator : m_smallAllocators)
         log(allocator);
index fa76d10f62ddcd4fb54541fa234b086fdc265849..5e6b2a075c0e54c53a4bd35c0b55380fcbb2fc11 100644 (file)
@@ -46,6 +46,8 @@ public:
     void* allocate(size_t);
     bool allocateFastCase(size_t, void*&);
     void* allocateSlowCase(size_t);
+    
+    void scavenge();
 
 private:
     SmallAllocator& smallAllocatorFor(size_t);
index 722393ed4ea784f51e12228da94caffb8ebe8d5b..20a913678161bcf494667bc22207be225d064530 100644 (file)
 
 namespace bmalloc {
 
-inline void* Cache::operator new(size_t size)
+void* Cache::operator new(size_t size)
 {
     return vmAllocate(vmSize(size));
 }
 
-inline void Cache::operator delete(void* p, size_t size)
+void Cache::operator delete(void* p, size_t size)
 {
     vmDeallocate(p, vmSize(size));
 }
 
-inline Cache::Cache()
+Cache::Cache()
     : m_deallocator()
     , m_allocator(m_deallocator)
 {
     // Ensure that the heap exists, so Allocator and Deallocator can assume it does.
     PerProcess<Heap>::get();
 }
+    
+void Cache::scavenge()
+{
+    m_allocator.scavenge();
+    m_deallocator.scavenge();
+}
 
 NO_INLINE void* Cache::allocateSlowCase(size_t size)
 {
index d1178ea580a3ac436b1f7c5a86e9ae10a2215da6..8938c3f3ae921d6bc936408712664a52e6466fd0 100644 (file)
@@ -46,6 +46,8 @@ public:
 
     Allocator& allocator() { return m_allocator; }
     Deallocator& deallocator() { return m_deallocator; }
+    
+    void scavenge();
 
 private:
     static bool allocateFastCase(size_t, void*&);
index 2e7cbf9af14a19023755dc197ca5aa2511c97793..991939e5a8ab2317862633bfc0d8174db0b48473 100644 (file)
@@ -46,6 +46,11 @@ Deallocator::Deallocator()
 }
 
 Deallocator::~Deallocator()
+{
+    scavenge();
+}
+    
+void Deallocator::scavenge()
 {
     processObjectLog();
     
index e01685fd73fc10546f6da691f528e4934673e8b3..e6987d538afce14c9d19ce2b4c656400c0a0bbe1 100644 (file)
@@ -49,7 +49,9 @@ public:
 
     void deallocateMediumLine(std::lock_guard<Mutex>&, MediumLine*);
     MediumLine* allocateMediumLine();
-
+    
+    void scavenge();
+    
 private:
     void deallocateLarge(void*);
     void deallocateXLarge(void*);
index 6923ee4d1951b0d01520ba1a293bdbab5d8013ae..0405501ea9253e7831ec5d050c0af8f6e6c43bb6 100644 (file)
@@ -38,6 +38,9 @@ namespace bmalloc {
 
 static inline void sleep(std::unique_lock<Mutex>& lock, std::chrono::milliseconds duration)
 {
+    if (duration == std::chrono::milliseconds(0))
+        return;
+    
     lock.unlock();
     std::this_thread::sleep_for(duration);
     lock.lock();
@@ -52,20 +55,25 @@ Heap::Heap(std::lock_guard<Mutex>&)
 void Heap::concurrentScavenge()
 {
     std::unique_lock<Mutex> lock(PerProcess<Heap>::mutex());
-    scavengeSmallPages(lock);
-    scavengeMediumPages(lock);
-    scavengeLargeRanges(lock);
+    scavenge(lock, scavengeSleepDuration);
+}
+    
+void Heap::scavenge(std::unique_lock<Mutex>& lock, std::chrono::milliseconds sleepDuration)
+{
+    scavengeSmallPages(lock, sleepDuration);
+    scavengeMediumPages(lock, sleepDuration);
+    scavengeLargeRanges(lock, sleepDuration);
 
-    sleep(lock, scavengeSleepDuration);
+    sleep(lock, sleepDuration);
 }
 
-void Heap::scavengeSmallPages(std::unique_lock<Mutex>& lock)
+void Heap::scavengeSmallPages(std::unique_lock<Mutex>& lock, std::chrono::milliseconds sleepDuration)
 {
     while (1) {
         if (m_isAllocatingPages) {
             m_isAllocatingPages = false;
 
-            sleep(lock, scavengeSleepDuration);
+            sleep(lock, sleepDuration);
             continue;
         }
 
@@ -75,13 +83,13 @@ void Heap::scavengeSmallPages(std::unique_lock<Mutex>& lock)
     }
 }
 
-void Heap::scavengeMediumPages(std::unique_lock<Mutex>& lock)
+void Heap::scavengeMediumPages(std::unique_lock<Mutex>& lock, std::chrono::milliseconds sleepDuration)
 {
     while (1) {
         if (m_isAllocatingPages) {
             m_isAllocatingPages = false;
 
-            sleep(lock, scavengeSleepDuration);
+            sleep(lock, sleepDuration);
             continue;
         }
 
@@ -91,13 +99,13 @@ void Heap::scavengeMediumPages(std::unique_lock<Mutex>& lock)
     }
 }
 
-void Heap::scavengeLargeRanges(std::unique_lock<Mutex>& lock)
+void Heap::scavengeLargeRanges(std::unique_lock<Mutex>& lock, std::chrono::milliseconds sleepDuration)
 {
     while (1) {
         if (m_isAllocatingPages) {
             m_isAllocatingPages = false;
 
-            sleep(lock, scavengeSleepDuration);
+            sleep(lock, sleepDuration);
             continue;
         }
 
index 8c6f6d6a31b223411f42effecc30ad3a13096b08..6c5c5cd4913f7e5b000b030f68a2ead9c6db1268 100644 (file)
@@ -61,6 +61,8 @@ public:
     void* allocateXLarge(std::lock_guard<Mutex>&, size_t);
     void deallocateXLarge(std::lock_guard<Mutex>&, void*);
 
+    void scavenge(std::unique_lock<Mutex>&, std::chrono::milliseconds sleepDuration);
+    
 private:
     ~Heap() = delete;
 
@@ -76,9 +78,9 @@ private:
     void mergeLargeRight(EndTag*&, BeginTag*&, Range&, bool& hasPhysicalPages);
     
     void concurrentScavenge();
-    void scavengeSmallPages(std::unique_lock<Mutex>&);
-    void scavengeMediumPages(std::unique_lock<Mutex>&);
-    void scavengeLargeRanges(std::unique_lock<Mutex>&);
+    void scavengeSmallPages(std::unique_lock<Mutex>&, std::chrono::milliseconds);
+    void scavengeMediumPages(std::unique_lock<Mutex>&, std::chrono::milliseconds);
+    void scavengeLargeRanges(std::unique_lock<Mutex>&, std::chrono::milliseconds);
 
     Vector<SmallLine*> m_smallLines;
     Vector<MediumLine*> m_mediumLines;
index 98c4a4a6a0dce9d4f669bcaa2557a59b58009980..b322437818c28fffd738f42dc8b8ba6a776a994b 100644 (file)
@@ -24,7 +24,9 @@
  */
 
 #include "Cache.h"
+#include "Heap.h"
 #include "LargeChunk.h"
+#include "PerProcess.h"
 #include "XLargeChunk.h"
 #include "Sizes.h"
 
@@ -78,6 +80,14 @@ inline void* realloc(void* object, size_t newSize)
     Cache::deallocate(object);
     return result;
 }
+    
+inline void scavenge()
+{
+    PerThread<Cache>::get()->scavenge();
+    
+    std::unique_lock<Mutex> lock(PerProcess<Heap>::mutex());
+    PerProcess<Heap>::get()->scavenge(lock, std::chrono::milliseconds(0));
+}
 
 } // namespace api
 } // namespace bmalloc
index e37d21f8620670c45ab8fecdbaba74e400fdb08f..43ad4a4f6eaceca03aa8e06f42a17ea914e5ca8e 100644 (file)
@@ -32,7 +32,8 @@ extern "C" {
 EXPORT void* mbmalloc(size_t);
 EXPORT void mbfree(void*, size_t);
 EXPORT void* mbrealloc(void*, size_t, size_t);
-
+EXPORT void mbscavenge();
+    
 void* mbmalloc(size_t size)
 {
     return bmalloc::api::malloc(size);
@@ -48,4 +49,9 @@ void* mbrealloc(void* p, size_t, size_t size)
     return bmalloc::api::realloc(p, size);
 }
 
+void mbscavenge()
+{
+    bmalloc::api::scavenge();
+}
+
 } // extern "C"