Title: [167570] trunk/Source/bmalloc
Revision
167570
Author
[email protected]
Date
2014-04-20 12:33:14 -0700 (Sun, 20 Apr 2014)

Log Message

bmalloc: Segregate pages by objects size
https://bugs.webkit.org/show_bug.cgi?id=131909

Reviewed by Andreas Kling.

2% reduction in memory-at-end on the Membuster memory_warning benchmarks.

* bmalloc/Allocator.cpp:
(bmalloc::Allocator::allocateSlowCase):
* bmalloc/Allocator.h:
(bmalloc::Allocator::allocateFastCase):
(bmalloc::Allocator::smallAllocatorFor): Use the new shared helper
function for size class calculation.

* bmalloc/Deallocator.cpp:
(bmalloc::Deallocator::Deallocator):
(bmalloc::Deallocator::scavenge):
(bmalloc::Deallocator::deallocateSmallLine):
(bmalloc::Deallocator::allocateSmallLine):
* bmalloc/Deallocator.h: Keep a cache for every size class, since the
cache can't be shared anymore.

* bmalloc/Heap.cpp:
(bmalloc::Heap::allocateSmallLineSlowCase):
* bmalloc/Heap.h:
(bmalloc::Heap::deallocateSmallLine): Ditto.

(bmalloc::Heap::allocateSmallLine): Check size class in addition to
page refcount when allocating a line because we might have deallocated
the page and the recycled it for another size class.

(bmalloc::Heap::deallocateMediumLine):
(bmalloc::Heap::allocateMediumLine):
* bmalloc/Line.h:
(bmalloc::Line::refCount):
* bmalloc/Page.h:
(bmalloc::Page::refCount):
(bmalloc::Page::smallSizeClass):
(bmalloc::Page::setSmallSizeClass):
(bmalloc::Page<Traits>::refCount): Deleted.
* bmalloc/Sizes.h:
(bmalloc::Sizes::smallSizeClassFor): New shared API for computing
an index into an array from a size.

Modified Paths

Diff

Modified: trunk/Source/bmalloc/ChangeLog (167569 => 167570)


--- trunk/Source/bmalloc/ChangeLog	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/ChangeLog	2014-04-20 19:33:14 UTC (rev 167570)
@@ -1,3 +1,49 @@
+2014-04-20  Geoffrey Garen  <[email protected]>
+
+        bmalloc: Segregate pages by objects size
+        https://bugs.webkit.org/show_bug.cgi?id=131909
+
+        Reviewed by Andreas Kling.
+
+        2% reduction in memory-at-end on the Membuster memory_warning benchmarks.
+
+        * bmalloc/Allocator.cpp:
+        (bmalloc::Allocator::allocateSlowCase):
+        * bmalloc/Allocator.h:
+        (bmalloc::Allocator::allocateFastCase):
+        (bmalloc::Allocator::smallAllocatorFor): Use the new shared helper
+        function for size class calculation.
+
+        * bmalloc/Deallocator.cpp:
+        (bmalloc::Deallocator::Deallocator):
+        (bmalloc::Deallocator::scavenge):
+        (bmalloc::Deallocator::deallocateSmallLine):
+        (bmalloc::Deallocator::allocateSmallLine):
+        * bmalloc/Deallocator.h: Keep a cache for every size class, since the
+        cache can't be shared anymore.
+
+        * bmalloc/Heap.cpp:
+        (bmalloc::Heap::allocateSmallLineSlowCase):
+        * bmalloc/Heap.h:
+        (bmalloc::Heap::deallocateSmallLine): Ditto.
+
+        (bmalloc::Heap::allocateSmallLine): Check size class in addition to
+        page refcount when allocating a line because we might have deallocated
+        the page and the recycled it for another size class.
+
+        (bmalloc::Heap::deallocateMediumLine):
+        (bmalloc::Heap::allocateMediumLine):
+        * bmalloc/Line.h:
+        (bmalloc::Line::refCount):
+        * bmalloc/Page.h:
+        (bmalloc::Page::refCount):
+        (bmalloc::Page::smallSizeClass):
+        (bmalloc::Page::setSmallSizeClass):
+        (bmalloc::Page<Traits>::refCount): Deleted.
+        * bmalloc/Sizes.h:
+        (bmalloc::Sizes::smallSizeClassFor): New shared API for computing
+        an index into an array from a size.
+
 2014-04-19  Geoffrey Garen  <[email protected]>
 
         bmalloc: Improved alignment in LargeChunk

Modified: trunk/Source/bmalloc/bmalloc/Allocator.cpp (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Allocator.cpp	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Allocator.cpp	2014-04-20 19:33:14 UTC (rev 167570)
@@ -145,9 +145,10 @@
     BASSERT(!allocateFastCase(size, dummy));
 )
     if (size <= smallMax) {
-        SmallAllocator& allocator = smallAllocatorFor(size);
+        size_t smallSizeClass = smallSizeClassFor(size);
+        SmallAllocator& allocator = m_smallAllocators[smallSizeClass];
         log(allocator);
-        allocator.refill(m_deallocator.allocateSmallLine());
+        allocator.refill(m_deallocator.allocateSmallLine(smallSizeClass));
         return allocator.allocate();
     }
 

Modified: trunk/Source/bmalloc/bmalloc/Allocator.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Allocator.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Allocator.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -50,7 +50,6 @@
     void scavenge();
 
 private:
-    SmallAllocator& smallAllocatorFor(size_t);
     void* allocateFastCase(SmallAllocator&);
 
     void* allocateMedium(size_t);
@@ -72,18 +71,12 @@
     FixedVector<std::pair<MediumLine*, unsigned char>, mediumAllocatorLogCapacity> m_mediumAllocatorLog;
 };
 
-inline SmallAllocator& Allocator::smallAllocatorFor(size_t size)
-{
-    size_t index = mask((size - 1ul) / alignment, m_smallAllocators.size() - 1);
-    return m_smallAllocators[index];
-}
-
 inline bool Allocator::allocateFastCase(size_t size, void*& object)
 {
     if (size > smallMax)
         return false;
 
-    SmallAllocator& allocator = smallAllocatorFor(size);
+    SmallAllocator& allocator = m_smallAllocators[smallSizeClassFor(size)];
     if (!allocator.canAllocate())
         return false;
 

Modified: trunk/Source/bmalloc/bmalloc/Deallocator.cpp (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Deallocator.cpp	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Deallocator.cpp	2014-04-20 19:33:14 UTC (rev 167570)
@@ -40,7 +40,7 @@
 
 Deallocator::Deallocator()
     : m_objectLog()
-    , m_smallLineCache()
+    , m_smallLineCaches()
     , m_mediumLineCache()
 {
 }
@@ -57,8 +57,10 @@
     std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
     Heap* heap = PerProcess<Heap>::getFastCase();
     
-    while (m_smallLineCache.size())
-        heap->deallocateSmallLine(lock, m_smallLineCache.pop());
+    for (auto& smallLineCache : m_smallLineCaches) {
+        while (smallLineCache.size())
+            heap->deallocateSmallLine(lock, smallLineCache.pop());
+    }
     while (m_mediumLineCache.size())
         heap->deallocateMediumLine(lock, m_mediumLineCache.pop());
 }
@@ -119,23 +121,25 @@
 
 void Deallocator::deallocateSmallLine(std::lock_guard<StaticMutex>& lock, SmallLine* line)
 {
-    if (m_smallLineCache.size() == m_smallLineCache.capacity())
+    SmallLineCache& smallLineCache = m_smallLineCaches[SmallPage::get(line)->smallSizeClass()];
+    if (smallLineCache.size() == smallLineCache.capacity())
         return PerProcess<Heap>::getFastCase()->deallocateSmallLine(lock, line);
 
-    m_smallLineCache.push(line);
+    smallLineCache.push(line);
 }
 
-SmallLine* Deallocator::allocateSmallLine()
+SmallLine* Deallocator::allocateSmallLine(size_t smallSizeClass)
 {
-    if (!m_smallLineCache.size()) {
+    SmallLineCache& smallLineCache = m_smallLineCaches[smallSizeClass];
+    if (!smallLineCache.size()) {
         std::lock_guard<StaticMutex> lock(PerProcess<Heap>::mutex());
         Heap* heap = PerProcess<Heap>::getFastCase();
 
-        while (m_smallLineCache.size() != m_smallLineCache.capacity())
-            m_smallLineCache.push(heap->allocateSmallLine(lock));
+        while (smallLineCache.size() != smallLineCache.capacity())
+            smallLineCache.push(heap->allocateSmallLine(lock, smallSizeClass));
     }
 
-    return m_smallLineCache.pop();
+    return smallLineCache.pop();
 }
 
 void Deallocator::deallocateMediumLine(std::lock_guard<StaticMutex>& lock, MediumLine* line)

Modified: trunk/Source/bmalloc/bmalloc/Deallocator.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Deallocator.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Deallocator.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -45,7 +45,7 @@
     void deallocateSlowCase(void*);
 
     void deallocateSmallLine(std::lock_guard<StaticMutex>&, SmallLine*);
-    SmallLine* allocateSmallLine();
+    SmallLine* allocateSmallLine(size_t smallSizeClass);
 
     void deallocateMediumLine(std::lock_guard<StaticMutex>&, MediumLine*);
     MediumLine* allocateMediumLine();
@@ -53,13 +53,16 @@
     void scavenge();
     
 private:
+    typedef FixedVector<SmallLine*, smallLineCacheCapacity> SmallLineCache;
+    typedef FixedVector<MediumLine*, mediumLineCacheCapacity> MediumLineCache;
+
     void deallocateLarge(void*);
     void deallocateXLarge(void*);
     void processObjectLog();
 
     FixedVector<void*, deallocatorLogCapacity> m_objectLog;
-    FixedVector<SmallLine*, smallLineCacheCapacity> m_smallLineCache;
-    FixedVector<MediumLine*, mediumLineCacheCapacity> m_mediumLineCache;
+    std::array<SmallLineCache, smallMax / alignment> m_smallLineCaches;
+    MediumLineCache m_mediumLineCache;
 };
 
 inline bool Deallocator::deallocateFastCase(void* object)

Modified: trunk/Source/bmalloc/bmalloc/Heap.cpp (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Heap.cpp	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Heap.cpp	2014-04-20 19:33:14 UTC (rev 167570)
@@ -116,7 +116,7 @@
     }
 }
 
-SmallLine* Heap::allocateSmallLineSlowCase(std::lock_guard<StaticMutex>& lock)
+SmallLine* Heap::allocateSmallLineSlowCase(std::lock_guard<StaticMutex>& lock, size_t smallSizeClass)
 {
     m_isAllocatingPages = true;
 
@@ -130,9 +130,12 @@
     }();
 
     SmallLine* line = page->begin();
+    Vector<SmallLine*>& smallLines = m_smallLines[smallSizeClass];
     for (auto it = line + 1; it != page->end(); ++it)
-        m_smallLines.push(it);
+        smallLines.push(it);
 
+    BASSERT(!line->refCount(lock));
+    page->setSmallSizeClass(smallSizeClass);
     page->ref(lock);
     return line;
 }

Modified: trunk/Source/bmalloc/bmalloc/Heap.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Heap.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Heap.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -49,7 +49,7 @@
 public:
     Heap(std::lock_guard<StaticMutex>&);
 
-    SmallLine* allocateSmallLine(std::lock_guard<StaticMutex>&);
+    SmallLine* allocateSmallLine(std::lock_guard<StaticMutex>&, size_t smallSizeClass);
     void deallocateSmallLine(std::lock_guard<StaticMutex>&, SmallLine*);
 
     MediumLine* allocateMediumLine(std::lock_guard<StaticMutex>&);
@@ -66,7 +66,7 @@
 private:
     ~Heap() = delete;
 
-    SmallLine* allocateSmallLineSlowCase(std::lock_guard<StaticMutex>&);
+    SmallLine* allocateSmallLineSlowCase(std::lock_guard<StaticMutex>&, size_t smallSizeClass);
     MediumLine* allocateMediumLineSlowCase(std::lock_guard<StaticMutex>&);
 
     void* allocateLarge(Range, size_t);
@@ -82,7 +82,7 @@
     void scavengeMediumPages(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
     void scavengeLargeRanges(std::unique_lock<StaticMutex>&, std::chrono::milliseconds);
 
-    Vector<SmallLine*> m_smallLines;
+    std::array<Vector<SmallLine*>, smallMax / alignment> m_smallLines;
     Vector<MediumLine*> m_mediumLines;
 
     Vector<SmallPage*> m_smallPages;
@@ -98,31 +98,35 @@
 
 inline void Heap::deallocateSmallLine(std::lock_guard<StaticMutex>& lock, SmallLine* line)
 {
+    BASSERT(!line->refCount(lock));
     SmallPage* page = SmallPage::get(line);
     if (page->deref(lock)) {
         m_smallPages.push(page);
         m_scavenger.run();
         return;
     }
-    m_smallLines.push(line);
+    m_smallLines[page->smallSizeClass()].push(line);
 }
 
-inline SmallLine* Heap::allocateSmallLine(std::lock_guard<StaticMutex>& lock)
+inline SmallLine* Heap::allocateSmallLine(std::lock_guard<StaticMutex>& lock, size_t smallSizeClass)
 {
-    while (m_smallLines.size()) {
-        SmallLine* line = m_smallLines.pop();
+    Vector<SmallLine*>& smallLines = m_smallLines[smallSizeClass];
+    while (smallLines.size()) {
+        SmallLine* line = smallLines.pop();
         SmallPage* page = SmallPage::get(line);
-        if (!page->refCount(lock)) // The line was promoted to the small pages list.
+        if (!page->refCount(lock) || page->smallSizeClass() != smallSizeClass) // The line was promoted to the small pages list.
             continue;
+        BASSERT(!line->refCount(lock));
         page->ref(lock);
         return line;
     }
 
-    return allocateSmallLineSlowCase(lock);
+    return allocateSmallLineSlowCase(lock, smallSizeClass);
 }
 
 inline void Heap::deallocateMediumLine(std::lock_guard<StaticMutex>& lock, MediumLine* line)
 {
+    BASSERT(!line->refCount(lock));
     MediumPage* page = MediumPage::get(line);
     if (page->deref(lock)) {
         m_mediumPages.push(page);
@@ -139,6 +143,7 @@
         MediumPage* page = MediumPage::get(line);
         if (!page->refCount(lock)) // The line was promoted to the medium pages list.
             continue;
+        BASSERT(!line->refCount(lock));
         page->ref(lock);
         return line;
     }

Modified: trunk/Source/bmalloc/bmalloc/Line.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Line.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Line.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -47,6 +47,7 @@
 
     void concurrentRef(unsigned char = 1);
     bool deref(std::lock_guard<StaticMutex>&, unsigned char = 1);
+    unsigned refCount(std::lock_guard<StaticMutex>&) { return m_refCount; }
     
     char* begin();
     char* end();

Modified: trunk/Source/bmalloc/bmalloc/Page.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Page.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Page.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -47,13 +47,17 @@
 
     void ref(std::lock_guard<StaticMutex>&);
     bool deref(std::lock_guard<StaticMutex>&);
-    unsigned refCount(std::lock_guard<StaticMutex>&);
+    unsigned refCount(std::lock_guard<StaticMutex>&) { return m_refCount; }
     
+    size_t smallSizeClass() { return m_smallSizeClass; }
+    void setSmallSizeClass(size_t smallSizeClass) { m_smallSizeClass = smallSizeClass; }
+    
     Line* begin();
     Line* end();
 
 private:
     unsigned char m_refCount;
+    unsigned char m_smallSizeClass;
 };
 
 template<typename Traits>
@@ -72,12 +76,6 @@
 }
 
 template<typename Traits>
-inline unsigned Page<Traits>::refCount(std::lock_guard<StaticMutex>&)
-{
-    return m_refCount;
-}
-
-template<typename Traits>
 inline auto Page<Traits>::get(Line* line) -> Page*
 {
     Chunk* chunk = Chunk::get(line);

Modified: trunk/Source/bmalloc/bmalloc/Sizes.h (167569 => 167570)


--- trunk/Source/bmalloc/bmalloc/Sizes.h	2014-04-20 19:02:13 UTC (rev 167569)
+++ trunk/Source/bmalloc/bmalloc/Sizes.h	2014-04-20 19:33:14 UTC (rev 167570)
@@ -89,6 +89,12 @@
     static const size_t mediumAllocatorLogCapacity = 8;
     
     static const std::chrono::milliseconds scavengeSleepDuration = std::chrono::milliseconds(512);
+
+    inline size_t smallSizeClassFor(size_t size)
+    {
+        static const size_t smallSizeClassMask = (smallMax / alignment) - 1;
+        return mask((size - 1ul) / alignment, smallSizeClassMask);
+    }
 };
 
 using namespace Sizes;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to