Title: [278278] trunk/Source/bmalloc
Revision
278278
Author
[email protected]
Date
2021-05-31 08:04:24 -0700 (Mon, 31 May 2021)

Log Message

[bmalloc] Make adaptive scavenging more precise
https://bugs.webkit.org/show_bug.cgi?id=226237

Reviewed by Geoffrey Garen.

This patch re-enables the adaptive scavenger for macOS.
It is much more precise when calling madvise() by keeping track of the
maximum extent of physically mapped memory in a LargeRange.  For example,
in the prior code, we'd return a small range back to a Gigacage LargeRange
whithout any physical pages.  When we scavenge that LargeRange, we madvise()
the whole Gigacage range.  Although this didn't cause correctness issues,
it was quite wasteful.

In the tests I did with this patch compared to the earlier adaptive change,
the number of madvise calls we made drops by ~18% and the time spent in those
calls dropped ~13% on an Apple silicon mac and ~30% on an x86 mac.
This was measured using dtrace running JetStream2 from the command line.
RAMification results improved ~1% over the adptive change.

There is the possible future optimization where we also keep track of the
first address of physically mapped memory in a LargeRange.  Since bmalloc
allocates memory from lower addresses first, it is thought that the change
in this patch is sufficient to reduce not only the number of madvise calls,
but the time it takes to make those calls.

* bmalloc/BPlatform.h:
* bmalloc/Heap.cpp:
(bmalloc::Heap::decommitLargeRange):
(bmalloc::Heap::scavenge):
(bmalloc::Heap::allocateSmallChunk):
(bmalloc::Heap::deallocateSmallChunk):
(bmalloc::Heap::allocateSmallPage):
(bmalloc::Heap::splitAndAllocate):
(bmalloc::Heap::allocateLarge):
(bmalloc::Heap::tryAllocateLargeChunk):
(bmalloc::Heap::shrinkLarge):
(bmalloc::Heap::deallocateLarge):
(bmalloc::Heap::scavengeToHighWatermark): Deleted.
* bmalloc/Heap.h:
* bmalloc/IsoDirectory.h:
* bmalloc/IsoDirectoryInlines.h:
(bmalloc::passedNumPages>::takeFirstEligible):
(bmalloc::passedNumPages>::scavenge):
(bmalloc::passedNumPages>::scavengeToHighWatermark): Deleted.
* bmalloc/IsoHeapImpl.h:
* bmalloc/IsoHeapImplInlines.h:
(bmalloc::IsoHeapImpl<Config>::scavengeToHighWatermark): Deleted.
* bmalloc/LargeMap.cpp:
(bmalloc::LargeMap::add):
* bmalloc/LargeRange.h:
(bmalloc::LargeRange::LargeRange):
(bmalloc::LargeRange::physicalExtent const):
(bmalloc::LargeRange::setPhysicalExtent):
(bmalloc::LargeRange::resetPhysicalExtent):
(bmalloc::LargeRange::setUsedSinceLastScavenge):
(bmalloc::merge):
(bmalloc::LargeRange::split const):
(): Deleted.
* bmalloc/Scavenger.cpp:
(bmalloc::Scavenger::Scavenger):
(bmalloc::Scavenger::scavenge):
(bmalloc::Scavenger::threadRunLoop):
(bmalloc::Scavenger::timeSinceLastPartialScavenge): Deleted.
(bmalloc::Scavenger::partialScavenge): Deleted.
* bmalloc/Scavenger.h:
* bmalloc/SmallPage.h:
(bmalloc::SmallPage::setUsedSinceLastScavenge):

Modified Paths

Diff

Modified: trunk/Source/bmalloc/ChangeLog (278277 => 278278)


--- trunk/Source/bmalloc/ChangeLog	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/ChangeLog	2021-05-31 15:04:24 UTC (rev 278278)
@@ -1,3 +1,73 @@
+2021-05-31  Michael Saboff  <[email protected]>
+
+        [bmalloc] Make adaptive scavenging more precise
+        https://bugs.webkit.org/show_bug.cgi?id=226237
+
+        Reviewed by Geoffrey Garen.
+
+        This patch re-enables the adaptive scavenger for macOS.
+        It is much more precise when calling madvise() by keeping track of the
+        maximum extent of physically mapped memory in a LargeRange.  For example,
+        in the prior code, we'd return a small range back to a Gigacage LargeRange
+        whithout any physical pages.  When we scavenge that LargeRange, we madvise()
+        the whole Gigacage range.  Although this didn't cause correctness issues,
+        it was quite wasteful.
+
+        In the tests I did with this patch compared to the earlier adaptive change,
+        the number of madvise calls we made drops by ~18% and the time spent in those
+        calls dropped ~13% on an Apple silicon mac and ~30% on an x86 mac.
+        This was measured using dtrace running JetStream2 from the command line.
+        RAMification results improved ~1% over the adptive change.
+
+        There is the possible future optimization where we also keep track of the
+        first address of physically mapped memory in a LargeRange.  Since bmalloc
+        allocates memory from lower addresses first, it is thought that the change
+        in this patch is sufficient to reduce not only the number of madvise calls,
+        but the time it takes to make those calls.
+
+        * bmalloc/BPlatform.h:
+        * bmalloc/Heap.cpp:
+        (bmalloc::Heap::decommitLargeRange):
+        (bmalloc::Heap::scavenge):
+        (bmalloc::Heap::allocateSmallChunk):
+        (bmalloc::Heap::deallocateSmallChunk):
+        (bmalloc::Heap::allocateSmallPage):
+        (bmalloc::Heap::splitAndAllocate):
+        (bmalloc::Heap::allocateLarge):
+        (bmalloc::Heap::tryAllocateLargeChunk):
+        (bmalloc::Heap::shrinkLarge):
+        (bmalloc::Heap::deallocateLarge):
+        (bmalloc::Heap::scavengeToHighWatermark): Deleted.
+        * bmalloc/Heap.h:
+        * bmalloc/IsoDirectory.h:
+        * bmalloc/IsoDirectoryInlines.h:
+        (bmalloc::passedNumPages>::takeFirstEligible):
+        (bmalloc::passedNumPages>::scavenge):
+        (bmalloc::passedNumPages>::scavengeToHighWatermark): Deleted.
+        * bmalloc/IsoHeapImpl.h:
+        * bmalloc/IsoHeapImplInlines.h:
+        (bmalloc::IsoHeapImpl<Config>::scavengeToHighWatermark): Deleted.
+        * bmalloc/LargeMap.cpp:
+        (bmalloc::LargeMap::add):
+        * bmalloc/LargeRange.h:
+        (bmalloc::LargeRange::LargeRange):
+        (bmalloc::LargeRange::physicalExtent const):
+        (bmalloc::LargeRange::setPhysicalExtent):
+        (bmalloc::LargeRange::resetPhysicalExtent):
+        (bmalloc::LargeRange::setUsedSinceLastScavenge):
+        (bmalloc::merge):
+        (bmalloc::LargeRange::split const):
+        (): Deleted.
+        * bmalloc/Scavenger.cpp:
+        (bmalloc::Scavenger::Scavenger):
+        (bmalloc::Scavenger::scavenge):
+        (bmalloc::Scavenger::threadRunLoop):
+        (bmalloc::Scavenger::timeSinceLastPartialScavenge): Deleted.
+        (bmalloc::Scavenger::partialScavenge): Deleted.
+        * bmalloc/Scavenger.h:
+        * bmalloc/SmallPage.h:
+        (bmalloc::SmallPage::setUsedSinceLastScavenge):
+
 2021-05-21  Michael Saboff  <[email protected]>
 
         [bmalloc] Rollout r276266 because WebKit processes are spending much more time in madvise

Modified: trunk/Source/bmalloc/bmalloc/BPlatform.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/BPlatform.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/BPlatform.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -309,12 +309,6 @@
 /* This is used for debugging when hacking on how bmalloc calculates its physical footprint. */
 #define ENABLE_PHYSICAL_PAGE_MAP 0
 
-#if BPLATFORM(MAC)
-#define BUSE_PARTIAL_SCAVENGE 1
-#else
-#define BUSE_PARTIAL_SCAVENGE 0
-#endif
-
 #if !defined(BUSE_PRECOMPUTED_CONSTANTS_VMPAGE4K)
 #define BUSE_PRECOMPUTED_CONSTANTS_VMPAGE4K 1
 #endif

Modified: trunk/Source/bmalloc/bmalloc/Heap.cpp (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/Heap.cpp	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/Heap.cpp	2021-05-31 15:04:24 UTC (rev 278278)
@@ -65,7 +65,7 @@
         m_gigacageSize = size;
         ptrdiff_t offset = roundDownToMultipleOf(vmPageSize(), random[1] % (gigacageSize - size));
         void* base = reinterpret_cast<unsigned char*>(gigacageBasePtr) + offset;
-        m_largeFree.add(LargeRange(base, size, 0, 0));
+        m_largeFree.add(LargeRange(base, size, 0, 0, base));
     }
 #endif
     
@@ -108,10 +108,13 @@
 {
     m_footprint -= range.totalPhysicalSize();
     m_freeableMemory -= range.totalPhysicalSize();
-    decommitter.addLazy(range.begin(), range.size());
-    m_hasPendingDecommits = true;
+    if (range.totalPhysicalSize()) {
+        decommitter.addLazy(range.begin(), range.physicalEnd() - range.begin());
+        m_hasPendingDecommits = true;
+    }
     range.setStartPhysicalSize(0);
     range.setTotalPhysicalSize(0);
+    range.clearPhysicalEnd();
     BASSERT(range.isEligibile());
     range.setEligible(false);
 #if ENABLE_PHYSICAL_PAGE_MAP 
@@ -119,11 +122,7 @@
 #endif
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
-void Heap::scavenge(UniqueLockHolder& lock, BulkDecommit& decommitter)
-#else
 void Heap::scavenge(UniqueLockHolder& lock, BulkDecommit& decommitter, size_t& deferredDecommits)
-#endif
 {
     for (auto& list : m_freePages) {
         for (auto* chunk : list) {
@@ -130,13 +129,11 @@
             for (auto* page : chunk->freePages()) {
                 if (!page->hasPhysicalPages())
                     continue;
-#if !BUSE(PARTIAL_SCAVENGE)
                 if (page->usedSinceLastScavenge()) {
                     page->clearUsedSinceLastScavenge();
                     deferredDecommits++;
                     continue;
                 }
-#endif
 
                 size_t pageSize = bmalloc::pageSize(&list - &m_freePages[0]);
                 size_t decommitSize = physicalPageSizeSloppy(page->begin()->begin(), pageSize);
@@ -157,37 +154,15 @@
     }
 
     for (LargeRange& range : m_largeFree) {
-#if BUSE(PARTIAL_SCAVENGE)
-        m_highWatermark = std::min(m_highWatermark, static_cast<void*>(range.begin()));
-#else
         if (range.usedSinceLastScavenge()) {
             range.clearUsedSinceLastScavenge();
             deferredDecommits++;
             continue;
         }
-#endif
         decommitLargeRange(lock, range, decommitter);
     }
-
-#if BUSE(PARTIAL_SCAVENGE)
-    m_freeableMemory = 0;
-#endif
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
-void Heap::scavengeToHighWatermark(UniqueLockHolder& lock, BulkDecommit& decommitter)
-{
-    void* newHighWaterMark = nullptr;
-    for (LargeRange& range : m_largeFree) {
-        if (range.begin() <= m_highWatermark)
-            newHighWaterMark = std::min(newHighWaterMark, static_cast<void*>(range.begin()));
-        else
-            decommitLargeRange(lock, range, decommitter);
-    }
-    m_highWatermark = newHighWaterMark;
-}
-#endif
-
 void Heap::deallocateLineCache(UniqueLockHolder&, LineCache& lineCache)
 {
     for (auto& list : lineCache) {
@@ -218,26 +193,15 @@
 
         m_objectTypes.set(lock, chunk, ObjectType::Small);
 
-        size_t accountedInFreeable = 0;
         forEachPage(chunk, pageSize, [&](SmallPage* page) {
             page->setHasPhysicalPages(true);
-#if !BUSE(PARTIAL_SCAVENGE)
             page->setUsedSinceLastScavenge();
-#endif
             page->setHasFreeLines(lock, true);
             chunk->freePages().push(page);
-            accountedInFreeable += pageSize;
         });
 
-        m_freeableMemory += accountedInFreeable;
+        m_freeableMemory += chunkSize;
 
-        auto metadataSize = Chunk::metadataSize(pageSize);
-        vmDeallocatePhysicalPagesSloppy(chunk->address(sizeof(Chunk)), metadataSize - sizeof(Chunk));
-
-        auto decommitSize = chunkSize - metadataSize - accountedInFreeable;
-        if (decommitSize > 0)
-            vmDeallocatePhysicalPagesSloppy(chunk->address(chunkSize - decommitSize), decommitSize);
-
         m_scavenger->schedule(0);
 
         return chunk;
@@ -253,24 +217,23 @@
     
     size_t size = m_largeAllocated.remove(chunk);
     size_t totalPhysicalSize = size;
+    size_t chunkPageSize = pageSize(pageClass);
+    SmallPage* firstPageWithoutPhysicalPages = nullptr;
 
-    size_t accountedInFreeable = 0;
-
-    bool hasPhysicalPages = true;
-    forEachPage(chunk, pageSize(pageClass), [&](SmallPage* page) {
+    void* physicalEnd = chunk->address(chunk->metadataSize(chunkPageSize));
+    forEachPage(chunk, chunkPageSize, [&](SmallPage* page) {
         size_t physicalSize = physicalPageSizeSloppy(page->begin()->begin(), pageSize(pageClass));
         if (!page->hasPhysicalPages()) {
             totalPhysicalSize -= physicalSize;
-            hasPhysicalPages = false;
+            if (!firstPageWithoutPhysicalPages)
+                firstPageWithoutPhysicalPages = page;
         } else
-            accountedInFreeable += physicalSize;
+            physicalEnd = page->begin()->begin() + physicalSize;
     });
 
-    m_freeableMemory -= accountedInFreeable;
-    m_freeableMemory += totalPhysicalSize;
+    size_t startPhysicalSize = firstPageWithoutPhysicalPages ? firstPageWithoutPhysicalPages->begin()->begin() - chunk->bytes() : size;
 
-    size_t startPhysicalSize = hasPhysicalPages ? size : 0;
-    m_largeFree.add(LargeRange(chunk, size, startPhysicalSize, totalPhysicalSize));
+    m_largeFree.add(LargeRange(chunk, size, startPhysicalSize, totalPhysicalSize, chunk->address(startPhysicalSize)));
 }
 
 SmallPage* Heap::allocateSmallPage(UniqueLockHolder& lock, size_t sizeClass, LineCache& lineCache, FailureAction action)
@@ -283,8 +246,6 @@
     if (!m_lineCache[sizeClass].isEmpty())
         return m_lineCache[sizeClass].popFront();
 
-    m_scavenger->didStartGrowing();
-    
     SmallPage* page = [&]() -> SmallPage* {
         size_t pageClass = m_constants.pageClass(sizeClass);
         
@@ -314,9 +275,7 @@
             m_physicalPageMap.commit(page->begin()->begin(), pageSize);
 #endif
         }
-#if !BUSE(PARTIAL_SCAVENGE)
         page->setUsedSinceLastScavenge();
-#endif
 
         return page;
     }();
@@ -525,6 +484,7 @@
         vmAllocatePhysicalPagesSloppy(range.begin() + range.startPhysicalSize(), range.size() - range.startPhysicalSize());
         range.setStartPhysicalSize(range.size());
         range.setTotalPhysicalSize(range.size());
+        range.setPhysicalEnd(range.begin() + range.size());
 #if ENABLE_PHYSICAL_PAGE_MAP 
         m_physicalPageMap.commit(range.begin(), range.size());
 #endif
@@ -560,8 +520,6 @@
 
     BASSERT(isPowerOfTwo(alignment));
     
-    m_scavenger->didStartGrowing();
-    
     size_t roundedSize = size ? roundUpToMultipleOf(largeAlignment, size) : largeAlignment;
     ASSERT_OR_RETURN_ON_FAILURE(roundedSize >= size); // Check for overflow
     size = roundedSize;
@@ -590,9 +548,6 @@
     m_freeableMemory -= range.totalPhysicalSize();
 
     void* result = splitAndAllocate(lock, range, alignment, size).begin();
-#if BUSE(PARTIAL_SCAVENGE)
-    m_highWatermark = std::max(m_highWatermark, result);
-#endif
     ASSERT_OR_RETURN_ON_FAILURE(result);
     return result;
 
@@ -621,7 +576,7 @@
     PerProcess<Zone>::get()->addRange(Range(memory, size));
 #endif
 
-    return LargeRange(memory, size, 0, 0);
+    return LargeRange(memory, size, 0, 0, memory);
 }
 
 size_t Heap::largeSize(UniqueLockHolder&, void* object)
@@ -634,7 +589,7 @@
     BASSERT(object.size() > newSize);
 
     size_t size = m_largeAllocated.remove(object.begin());
-    LargeRange range = LargeRange(object, size, size);
+    LargeRange range = LargeRange(object, size, size, object.begin() + size);
     splitAndAllocate(lock, range, alignment, newSize);
 
     m_scavenger->schedule(size);
@@ -643,7 +598,7 @@
 void Heap::deallocateLarge(UniqueLockHolder&, void* object)
 {
     size_t size = m_largeAllocated.remove(object);
-    m_largeFree.add(LargeRange(object, size, size, size));
+    m_largeFree.add(LargeRange(object, size, size, size, static_cast<char*>(object) + size));
     m_freeableMemory += size;
     m_scavenger->schedule(size);
 }

Modified: trunk/Source/bmalloc/bmalloc/Heap.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/Heap.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/Heap.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -74,12 +74,7 @@
     size_t largeSize(UniqueLockHolder&, void*);
     void shrinkLarge(UniqueLockHolder&, const Range&, size_t);
 
-#if BUSE(PARTIAL_SCAVENGE)
-    void scavengeToHighWatermark(UniqueLockHolder&, BulkDecommit&);
-    void scavenge(UniqueLockHolder&, BulkDecommit&);
-#else
     void scavenge(UniqueLockHolder&, BulkDecommit&, size_t& deferredDecommits);
-#endif
     void scavenge(UniqueLockHolder&, BulkDecommit&, size_t& freed, size_t goal);
 
     size_t freeableMemory(UniqueLockHolder&);
@@ -147,10 +142,6 @@
 #if ENABLE_PHYSICAL_PAGE_MAP 
     PhysicalPageMap m_physicalPageMap;
 #endif
-    
-#if BUSE(PARTIAL_SCAVENGE)
-    void* m_highWatermark { nullptr };
-#endif
 };
 
 inline void Heap::allocateSmallBumpRanges(

Modified: trunk/Source/bmalloc/bmalloc/IsoDirectory.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/IsoDirectory.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/IsoDirectory.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -76,9 +76,6 @@
     // Iterate over all empty and committed pages, and put them into the vector. This also records the
     // pages as being decommitted. It's the caller's job to do the actual decommitting.
     void scavenge(const LockHolder&, Vector<DeferredDecommit>&);
-#if BUSE(PARTIAL_SCAVENGE)
-    void scavengeToHighWatermark(const LockHolder&, Vector<DeferredDecommit>&);
-#endif
 
     template<typename Func>
     void forEachCommittedPage(const LockHolder&, const Func&);
@@ -93,9 +90,6 @@
     Bits<numPages> m_empty;
     Bits<numPages> m_committed;
     unsigned m_firstEligibleOrDecommitted { 0 };
-#if BUSE(PARTIAL_SCAVENGE)
-    unsigned m_highWatermark { 0 };
-#endif
 };
 
 } // namespace bmalloc

Modified: trunk/Source/bmalloc/bmalloc/IsoDirectoryInlines.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/IsoDirectoryInlines.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/IsoDirectoryInlines.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -50,12 +50,7 @@
     if (pageIndex >= numPages)
         return EligibilityKind::Full;
 
-#if BUSE(PARTIAL_SCAVENGE)
-    m_highWatermark = std::max(pageIndex, m_highWatermark);
-#endif
-
     Scavenger& scavenger = *Scavenger::get();
-    scavenger.didStartGrowing();
     
     IsoPage<Config>* page = m_pages[pageIndex].get();
     
@@ -146,25 +141,9 @@
         [&] (size_t index) {
             scavengePage(locker, index, decommits);
         });
-#if BUSE(PARTIAL_SCAVENGE)
-    m_highWatermark = 0;
-#endif
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
 template<typename Config, unsigned passedNumPages>
-void IsoDirectory<Config, passedNumPages>::scavengeToHighWatermark(const LockHolder& locker, Vector<DeferredDecommit>& decommits)
-{
-    (m_empty & m_committed).forEachSetBit(
-        [&] (size_t index) {
-            if (index > m_highWatermark)
-                scavengePage(locker, index, decommits);
-        });
-    m_highWatermark = 0;
-}
-#endif
-
-template<typename Config, unsigned passedNumPages>
 template<typename Func>
 void IsoDirectory<Config, passedNumPages>::forEachCommittedPage(const LockHolder&, const Func& func)
 {

Modified: trunk/Source/bmalloc/bmalloc/IsoHeapImpl.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/IsoHeapImpl.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/IsoHeapImpl.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -49,9 +49,6 @@
     virtual ~IsoHeapImplBase();
     
     virtual void scavenge(Vector<DeferredDecommit>&) = 0;
-#if BUSE(PARTIAL_SCAVENGE)
-    virtual void scavengeToHighWatermark(Vector<DeferredDecommit>&) = 0;
-#endif
     
     void scavengeNow();
     static void finishScavenging(Vector<DeferredDecommit>&);
@@ -112,9 +109,6 @@
     void didBecomeEligibleOrDecommited(const LockHolder&, IsoDirectory<Config, IsoDirectoryPage<Config>::numPages>*);
     
     void scavenge(Vector<DeferredDecommit>&) override;
-#if BUSE(PARTIAL_SCAVENGE)
-    void scavengeToHighWatermark(Vector<DeferredDecommit>&) override;
-#endif
 
     unsigned allocatorOffset();
     unsigned deallocatorOffset();

Modified: trunk/Source/bmalloc/bmalloc/IsoHeapImplInlines.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/IsoHeapImplInlines.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/IsoHeapImplInlines.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -121,21 +121,6 @@
     m_directoryHighWatermark = 0;
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
-template<typename Config>
-void IsoHeapImpl<Config>::scavengeToHighWatermark(Vector<DeferredDecommit>& decommits)
-{
-    LockHolder locker(this->lock);
-    if (!m_directoryHighWatermark)
-        m_inlineDirectory.scavengeToHighWatermark(locker, decommits);
-    for (IsoDirectoryPage<Config>* page = m_headDirectory.get(); page; page = page->next) {
-        if (page->index() >= m_directoryHighWatermark)
-            page->payload.scavengeToHighWatermark(locker, decommits);
-    }
-    m_directoryHighWatermark = 0;
-}
-#endif
-
 inline size_t IsoHeapImplBase::freeableMemory()
 {
     return m_freeableMemory;

Modified: trunk/Source/bmalloc/bmalloc/IsoSharedHeapInlines.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/IsoSharedHeapInlines.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/IsoSharedHeapInlines.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -63,7 +63,6 @@
 BNO_INLINE void* IsoSharedHeap::allocateSlow(const LockHolder& locker, bool abortOnFailure)
 {
     Scavenger& scavenger = *Scavenger::get();
-    scavenger.didStartGrowing();
     scavenger.scheduleIfUnderMemoryPressure(IsoSharedPage::pageSize);
 
     IsoSharedPage* page = IsoSharedPage::tryCreate();

Modified: trunk/Source/bmalloc/bmalloc/LargeMap.cpp (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/LargeMap.cpp	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/LargeMap.cpp	2021-05-31 15:04:24 UTC (rev 278278)
@@ -76,9 +76,7 @@
         merged = merge(merged, m_free.pop(i--));
     }
 
-#if !BUSE(PARTIAL_SCAVENGE)
     merged.setUsedSinceLastScavenge();
-#endif
     m_free.push(merged);
 }
 

Modified: trunk/Source/bmalloc/bmalloc/LargeRange.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/LargeRange.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/LargeRange.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -37,40 +37,29 @@
         : Range()
         , m_startPhysicalSize(0)
         , m_totalPhysicalSize(0)
-#if !BUSE(PARTIAL_SCAVENGE)
+        , m_physicalEnd(begin())
         , m_isEligible(true)
         , m_usedSinceLastScavenge(false)
-#endif
     {
     }
 
-    LargeRange(const Range& other, size_t startPhysicalSize, size_t totalPhysicalSize)
+    LargeRange(const Range& other, size_t startPhysicalSize, size_t totalPhysicalSize, void* physicalEnd)
         : Range(other)
         , m_startPhysicalSize(startPhysicalSize)
         , m_totalPhysicalSize(totalPhysicalSize)
-#if !BUSE(PARTIAL_SCAVENGE)
+        , m_physicalEnd(static_cast<char*>(physicalEnd))
         , m_isEligible(true)
         , m_usedSinceLastScavenge(false)
-#endif
     {
         BASSERT(this->size() >= this->totalPhysicalSize());
         BASSERT(this->totalPhysicalSize() >= this->startPhysicalSize());
     }
 
-#if BUSE(PARTIAL_SCAVENGE)
-    LargeRange(void* begin, size_t size, size_t startPhysicalSize, size_t totalPhysicalSize)
+    LargeRange(void* begin, size_t size, size_t startPhysicalSize, size_t totalPhysicalSize, void* physicalEnd, bool usedSinceLastScavenge = false)
         : Range(begin, size)
         , m_startPhysicalSize(startPhysicalSize)
         , m_totalPhysicalSize(totalPhysicalSize)
-    {
-        BASSERT(this->size() >= this->totalPhysicalSize());
-        BASSERT(this->totalPhysicalSize() >= this->startPhysicalSize());
-    }
-#else
-    LargeRange(void* begin, size_t size, size_t startPhysicalSize, size_t totalPhysicalSize, bool usedSinceLastScavenge = false)
-        : Range(begin, size)
-        , m_startPhysicalSize(startPhysicalSize)
-        , m_totalPhysicalSize(totalPhysicalSize)
+        , m_physicalEnd(static_cast<char*>(physicalEnd))
         , m_isEligible(true)
         , m_usedSinceLastScavenge(usedSinceLastScavenge)
     {
@@ -77,7 +66,6 @@
         BASSERT(this->size() >= this->totalPhysicalSize());
         BASSERT(this->totalPhysicalSize() >= this->startPhysicalSize());
     }
-#endif
 
     // Returns a lower bound on physical size at the start of the range. Ranges that
     // span non-physical fragments use this number to remember the physical size of
@@ -98,6 +86,12 @@
     // doesn't really affect accuracy.
     size_t totalPhysicalSize() const { return m_totalPhysicalSize; }
     void setTotalPhysicalSize(size_t totalPhysicalSize) { m_totalPhysicalSize = totalPhysicalSize; }
+    
+    // This is the address past the end of physical memory in this range.
+    // When decomitting this range, we decommitt [begin(), physicalEnd).
+    char* physicalEnd() const { return m_physicalEnd; }
+    void setPhysicalEnd(void* physicalEnd) { m_physicalEnd = static_cast<char*>(physicalEnd); }
+    void clearPhysicalEnd() { m_physicalEnd = begin(); }
 
     std::pair<LargeRange, LargeRange> split(size_t) const;
 
@@ -104,11 +98,9 @@
     void setEligible(bool eligible) { m_isEligible = eligible; }
     bool isEligibile() const { return m_isEligible; }
 
-#if !BUSE(PARTIAL_SCAVENGE)
     bool usedSinceLastScavenge() const { return m_usedSinceLastScavenge; }
     void clearUsedSinceLastScavenge() { m_usedSinceLastScavenge = false; }
     void setUsedSinceLastScavenge() { m_usedSinceLastScavenge = true; }
-#endif
 
     bool operator<(const void* other) const { return begin() < other; }
     bool operator<(const LargeRange& other) const { return begin() < other.begin(); }
@@ -116,12 +108,9 @@
 private:
     size_t m_startPhysicalSize;
     size_t m_totalPhysicalSize;
-#if BUSE(PARTIAL_SCAVENGE)
-    bool m_isEligible { true };
-#else
+    char* m_physicalEnd;
     unsigned m_isEligible: 1;
     unsigned m_usedSinceLastScavenge: 1;
-#endif
 };
 
 inline bool canMerge(const LargeRange& a, const LargeRange& b)
@@ -144,18 +133,17 @@
 inline LargeRange merge(const LargeRange& a, const LargeRange& b)
 {
     const LargeRange& left = std::min(a, b);
-#if !BUSE(PARTIAL_SCAVENGE)
+    const LargeRange& right = std::max(a, b);
+    void* physicalEnd = right.totalPhysicalSize() ? right.physicalEnd() : left.physicalEnd();
     bool mergedUsedSinceLastScavenge = a.usedSinceLastScavenge() || b.usedSinceLastScavenge();
-#endif
     if (left.size() == left.startPhysicalSize()) {
         return LargeRange(
             left.begin(),
             a.size() + b.size(),
             a.startPhysicalSize() + b.startPhysicalSize(),
-            a.totalPhysicalSize() + b.totalPhysicalSize()
-#if !BUSE(PARTIAL_SCAVENGE)
+            a.totalPhysicalSize() + b.totalPhysicalSize(),
+            physicalEnd
             , mergedUsedSinceLastScavenge
-#endif
         );
         
     }
@@ -164,10 +152,9 @@
         left.begin(),
         a.size() + b.size(),
         left.startPhysicalSize(),
-        a.totalPhysicalSize() + b.totalPhysicalSize()
-#if !BUSE(PARTIAL_SCAVENGE)
+        a.totalPhysicalSize() + b.totalPhysicalSize(),
+        physicalEnd
         , mergedUsedSinceLastScavenge
-#endif
     );
 }
 
@@ -175,11 +162,12 @@
 {
     BASSERT(leftSize <= this->size());
     size_t rightSize = this->size() - leftSize;
+    char* physicalEnd = this->physicalEnd();
 
     if (leftSize <= startPhysicalSize()) {
         BASSERT(totalPhysicalSize() >= leftSize);
-        LargeRange left(begin(), leftSize, leftSize, leftSize);
-        LargeRange right(left.end(), rightSize, startPhysicalSize() - leftSize, totalPhysicalSize() - leftSize);
+        LargeRange left(begin(), leftSize, leftSize, leftSize, std::min(physicalEnd, begin() + leftSize));
+        LargeRange right(left.end(), rightSize, startPhysicalSize() - leftSize, totalPhysicalSize() - leftSize, std::max(physicalEnd, left.end()));
         return std::make_pair(left, right);
     }
 
@@ -194,8 +182,8 @@
         rightTotalPhysicalSize = rightSize;
     }
 
-    LargeRange left(begin(), leftSize, startPhysicalSize(), leftTotalPhysicalSize);
-    LargeRange right(left.end(), rightSize, 0, rightTotalPhysicalSize);
+    LargeRange left(begin(), leftSize, startPhysicalSize(), leftTotalPhysicalSize, std::min(physicalEnd, begin() + leftSize));
+    LargeRange right(left.end(), rightSize, 0, rightTotalPhysicalSize, std::max(physicalEnd, left.end()));
     return std::make_pair(left, right);
 }
 

Modified: trunk/Source/bmalloc/bmalloc/Scavenger.cpp (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/Scavenger.cpp	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/Scavenger.cpp	2021-05-31 15:04:24 UTC (rev 278278)
@@ -85,11 +85,7 @@
     dispatch_resume(m_pressureHandlerDispatchSource);
     dispatch_release(queue);
 #endif
-#if BUSE(PARTIAL_SCAVENGE)
-    m_waitTime = std::chrono::milliseconds(m_isInMiniMode ? 200 : 2000);
-#else
     m_waitTime = std::chrono::milliseconds(10);
-#endif
 
     m_thread = std::thread(&threadEntryPoint, this);
 }
@@ -120,12 +116,6 @@
     m_condition.notify_all();
 }
 
-void Scavenger::didStartGrowing()
-{
-    // We don't really need to lock here, since this is just a heuristic.
-    m_isProbablyGrowing = true;
-}
-
 void Scavenger::scheduleIfUnderMemoryPressure(size_t bytes)
 {
     LockHolder lock(mutex());
@@ -146,7 +136,6 @@
     if (!isUnderMemoryPressure())
         return;
 
-    m_isProbablyGrowing = false;
     run(lock);
 }
 
@@ -158,7 +147,6 @@
     if (willRunSoon())
         return;
     
-    m_isProbablyGrowing = false;
     runSoon(lock);
 }
 
@@ -187,14 +175,6 @@
     return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_lastFullScavengeTime);
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
-std::chrono::milliseconds Scavenger::timeSinceLastPartialScavenge()
-{
-    UniqueLockHolder lock(mutex());
-    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_lastPartialScavengeTime);
-}
-#endif
-
 void Scavenger::enableMiniMode()
 {
     m_isInMiniMode = true; // We just store to this racily. The scavenger thread will eventually pick up the right value.
@@ -220,25 +200,17 @@
 
         {
             PrintTime printTime("\nfull scavenge under lock time");
-#if !BUSE(PARTIAL_SCAVENGE)
             size_t deferredDecommits = 0;
-#endif
             UniqueLockHolder lock(Heap::mutex());
             for (unsigned i = numHeaps; i--;) {
                 if (!isActiveHeapKind(static_cast<HeapKind>(i)))
                     continue;
-#if BUSE(PARTIAL_SCAVENGE)
-                PerProcess<PerHeapKind<Heap>>::get()->at(i).scavenge(lock, decommitter);
-#else
                 PerProcess<PerHeapKind<Heap>>::get()->at(i).scavenge(lock, decommitter, deferredDecommits);
-#endif
             }
             decommitter.processEager();
 
-#if !BUSE(PARTIAL_SCAVENGE)
             if (deferredDecommits)
                 m_state = State::RunSoon;
-#endif
         }
 
         {
@@ -279,78 +251,6 @@
     }
 }
 
-#if BUSE(PARTIAL_SCAVENGE)
-void Scavenger::partialScavenge()
-{
-    if (!m_isEnabled)
-        return;
-
-    UniqueLockHolder lock(m_scavengingMutex);
-
-    if (verbose) {
-        fprintf(stderr, "--------------------------------\n");
-        fprintf(stderr, "--before partial scavenging--\n");
-        dumpStats();
-    }
-
-    {
-        BulkDecommit decommitter;
-        {
-            PrintTime printTime("\npartialScavenge under lock time");
-            UniqueLockHolder lock(Heap::mutex());
-            for (unsigned i = numHeaps; i--;) {
-                if (!isActiveHeapKind(static_cast<HeapKind>(i)))
-                    continue;
-                Heap& heap = PerProcess<PerHeapKind<Heap>>::get()->at(i);
-                size_t freeableMemory = heap.freeableMemory(lock);
-                if (freeableMemory < 4 * MB)
-                    continue;
-                heap.scavengeToHighWatermark(lock, decommitter);
-            }
-
-            decommitter.processEager();
-        }
-
-        {
-            PrintTime printTime("partialScavenge lazy decommit time");
-            decommitter.processLazy();
-        }
-
-        {
-            PrintTime printTime("partialScavenge mark all as eligible time");
-            LockHolder lock(Heap::mutex());
-            for (unsigned i = numHeaps; i--;) {
-                if (!isActiveHeapKind(static_cast<HeapKind>(i)))
-                    continue;
-                Heap& heap = PerProcess<PerHeapKind<Heap>>::get()->at(i);
-                heap.markAllLargeAsEligibile(lock);
-            }
-        }
-    }
-
-    {
-        RELEASE_BASSERT(!m_deferredDecommits.size());
-        AllIsoHeaps::get()->forEach(
-            [&] (IsoHeapImplBase& heap) {
-                heap.scavengeToHighWatermark(m_deferredDecommits);
-            });
-        IsoHeapImplBase::finishScavenging(m_deferredDecommits);
-        m_deferredDecommits.shrink(0);
-    }
-
-    if (verbose) {
-        fprintf(stderr, "--after partial scavenging--\n");
-        dumpStats();
-        fprintf(stderr, "--------------------------------\n");
-    }
-
-    {
-        UniqueLockHolder lock(mutex());
-        m_lastPartialScavengeTime = std::chrono::steady_clock::now();
-    }
-}
-#endif
-
 size_t Scavenger::freeableMemory()
 {
     size_t result = 0;
@@ -432,69 +332,6 @@
             fprintf(stderr, "--------------------------------\n");
         }
 
-#if BUSE(PARTIAL_SCAVENGE)
-        enum class ScavengeMode {
-            None,
-            Partial,
-            Full
-        };
-
-        size_t freeableMemory = this->freeableMemory();
-
-        ScavengeMode scavengeMode = [&] {
-            auto timeSinceLastFullScavenge = this->timeSinceLastFullScavenge();
-            auto timeSinceLastPartialScavenge = this->timeSinceLastPartialScavenge();
-            auto timeSinceLastScavenge = std::min(timeSinceLastPartialScavenge, timeSinceLastFullScavenge);
-
-            if (isUnderMemoryPressure() && freeableMemory > 1 * MB && timeSinceLastScavenge > std::chrono::milliseconds(5))
-                return ScavengeMode::Full;
-
-            if (!m_isProbablyGrowing) {
-                if (timeSinceLastFullScavenge < std::chrono::milliseconds(1000) && !m_isInMiniMode)
-                    return ScavengeMode::Partial;
-                return ScavengeMode::Full;
-            }
-
-            if (m_isInMiniMode) {
-                if (timeSinceLastFullScavenge < std::chrono::milliseconds(200))
-                    return ScavengeMode::Partial;
-                return ScavengeMode::Full;
-            }
-
-#if BCPU(X86_64)
-            auto partialScavengeInterval = std::chrono::milliseconds(12000);
-#else
-            auto partialScavengeInterval = std::chrono::milliseconds(8000);
-#endif
-            if (timeSinceLastScavenge < partialScavengeInterval) {
-                // Rate limit partial scavenges.
-                return ScavengeMode::None;
-            }
-            if (freeableMemory < 25 * MB)
-                return ScavengeMode::None;
-            if (5 * freeableMemory < footprint())
-                return ScavengeMode::None;
-            return ScavengeMode::Partial;
-        }();
-
-        m_isProbablyGrowing = false;
-
-        switch (scavengeMode) {
-        case ScavengeMode::None: {
-            runSoon();
-            break;
-        }
-        case ScavengeMode::Partial: {
-            partialScavenge();
-            runSoon();
-            break;
-        }
-        case ScavengeMode::Full: {
-            scavenge();
-            break;
-        }
-        }
-#else
         std::chrono::steady_clock::time_point start { std::chrono::steady_clock::now() };
         
         scavenge();
@@ -509,14 +346,13 @@
         // FIXME: We need to investigate mini-mode's adjustment.
         // https://bugs.webkit.org/show_bug.cgi?id=203987
         if (!m_isInMiniMode) {
-            timeSpentScavenging *= 150;
+            timeSpentScavenging *= s_newWaitMultiplier;
             std::chrono::milliseconds newWaitTime = std::chrono::duration_cast<std::chrono::milliseconds>(timeSpentScavenging);
-            m_waitTime = std::min(std::max(newWaitTime, std::chrono::milliseconds(100)), std::chrono::milliseconds(10000));
+            m_waitTime = std::min(std::max(newWaitTime, std::chrono::milliseconds(s_minWaitTimeMilliseconds)), std::chrono::milliseconds(s_maxWaitTimeMilliseconds));
         }
 
         if (verbose)
             fprintf(stderr, "new wait time %lldms\n", static_cast<long long int>(m_waitTime.count()));
-#endif
     }
 }
 

Modified: trunk/Source/bmalloc/bmalloc/Scavenger.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/Scavenger.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/Scavenger.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -59,7 +59,6 @@
     bool willRunSoon() { return m_state > State::Sleep; }
     void runSoon();
     
-    BEXPORT void didStartGrowing();
     BEXPORT void scheduleIfUnderMemoryPressure(size_t bytes);
     BEXPORT void schedule(size_t bytes);
 
@@ -92,15 +91,10 @@
     void setThreadName(const char*);
 
     std::chrono::milliseconds timeSinceLastFullScavenge();
-#if BUSE(PARTIAL_SCAVENGE)
-    std::chrono::milliseconds timeSinceLastPartialScavenge();
-    void partialScavenge();
-#endif
 
     std::atomic<State> m_state { State::Sleep };
     size_t m_scavengerBytes { 0 };
     std::chrono::milliseconds m_waitTime;
-    bool m_isProbablyGrowing { false };
     bool m_isInMiniMode { false };
     
     Mutex m_scavengingMutex;
@@ -108,9 +102,6 @@
 
     std::thread m_thread;
     std::chrono::steady_clock::time_point m_lastFullScavengeTime { std::chrono::steady_clock::now() };
-#if BUSE(PARTIAL_SCAVENGE)
-    std::chrono::steady_clock::time_point m_lastPartialScavengeTime { std::chrono::steady_clock::now() };
-#endif
 
 #if BOS(DARWIN)
     dispatch_source_t m_pressureHandlerDispatchSource;
@@ -117,6 +108,16 @@
     qos_class_t m_requestedScavengerThreadQOSClass { QOS_CLASS_USER_INITIATED };
 #endif
     
+#if BPLATFORM(MAC)
+    const unsigned s_newWaitMultiplier = 300;
+    const unsigned s_minWaitTimeMilliseconds = 750;
+    const unsigned s_maxWaitTimeMilliseconds = 20000;
+#else
+    const unsigned s_newWaitMultiplier = 150;
+    const unsigned s_minWaitTimeMilliseconds = 100;
+    const unsigned s_maxWaitTimeMilliseconds = 10000;
+#endif
+
     Vector<DeferredDecommit> m_deferredDecommits;
     bool m_isEnabled { true };
 };

Modified: trunk/Source/bmalloc/bmalloc/SmallPage.h (278277 => 278278)


--- trunk/Source/bmalloc/bmalloc/SmallPage.h	2021-05-31 15:02:54 UTC (rev 278277)
+++ trunk/Source/bmalloc/bmalloc/SmallPage.h	2021-05-31 15:04:24 UTC (rev 278278)
@@ -51,11 +51,9 @@
     bool hasPhysicalPages() { return m_hasPhysicalPages; }
     void setHasPhysicalPages(bool hasPhysicalPages) { m_hasPhysicalPages = hasPhysicalPages; }
 
-#if !BUSE(PARTIAL_SCAVENGE)
     bool usedSinceLastScavenge() { return m_usedSinceLastScavenge; }
     void clearUsedSinceLastScavenge() { m_usedSinceLastScavenge = false; }
     void setUsedSinceLastScavenge() { m_usedSinceLastScavenge = true; }
-#endif
 
     SmallLine* begin();
 
@@ -65,9 +63,7 @@
 private:
     unsigned char m_hasFreeLines: 1;
     unsigned char m_hasPhysicalPages: 1;
-#if !BUSE(PARTIAL_SCAVENGE)
     unsigned char m_usedSinceLastScavenge: 1;
-#endif
     unsigned char m_refCount: 7;
     unsigned char m_sizeClass;
     unsigned char m_slide;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to