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 1effdf8..8c07029 100644 (file)
@@ -1,5 +1,25 @@
 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
         https://bugs.webkit.org/show_bug.cgi?id=131627
 
index c394842..6f6633f 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 b02f113..a873611 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 1f40c5d..546a886 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 7a0db28..cc77347 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 23fbd55..de31220 100644 (file)
@@ -1,5 +1,47 @@
 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
         https://bugs.webkit.org/show_bug.cgi?id=131658
 
index 59d5cf8..8433763 100644 (file)
@@ -51,6 +51,11 @@ Allocator::Allocator(Deallocator& deallocator)
 
 Allocator::~Allocator()
 {
+    scavenge();
+}
+    
+void Allocator::scavenge()
+{
     for (auto& allocator : m_smallAllocators)
         log(allocator);
     processSmallAllocatorLog();
index fa76d10..5e6b2a0 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 722393e..20a9136 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 d1178ea..8938c3f 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 2e7cbf9..991939e 100644 (file)
@@ -47,6 +47,11 @@ Deallocator::Deallocator()
 
 Deallocator::~Deallocator()
 {
+    scavenge();
+}
+    
+void Deallocator::scavenge()
+{
     processObjectLog();
     
     std::lock_guard<Mutex> lock(PerProcess<Heap>::mutex());
index e01685f..e6987d5 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 6923ee4..0405501 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 8c6f6d6..6c5c5cd 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 98c4a4a..b322437 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 e37d21f..43ad4a4 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"