⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 276517 in webkit


Ignore:
Timestamp:
Apr 23, 2021, 2:29:59 PM (5 years ago)
Author:
Ruben Turcios
Message:

Cherry-pick r276324. rdar://problem/77086404

FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
https://bugs.webkit.org/show_bug.cgi?id=224817

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Right now we try to determine if too many pages are paged out by
dereferencing them and bailing out of the GC if we go over a
deadline. While this works if the only goal is to avoid causing
extensive thrashing on spinny disks (HDD), it doesn't prevent
thrashing when access to disk is fast (e.g. SSD). This is because
on fast disks the proportional time to load the memory from disk
is much lower. Additionally, on SSDs in particular we don't want
to load the pages into RAM then bail as that will force a
different page onto disk, increasing wear.

This patch switches to asking the OS if each MarkedBlock is paged
out. Then if we are over a threshold we wait until we would have
GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
percentage of "slow" pages (paged out or compressed) needed to
defer the GC. The idea behind that threshold is that if we add
that many pages then the same number of pages would be forced
out of RAM for us to do a GC anyway (in the limit).

  • heap/BlockDirectory.cpp: (JSC::BlockDirectory::updatePercentageOfPagedOutPages): (JSC::BlockDirectory::isPagedOut): Deleted.
  • heap/BlockDirectory.h:
  • heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection):
  • heap/Heap.cpp: (JSC::Heap::isPagedOut):
  • heap/Heap.h:
  • heap/MarkedSpace.cpp: (JSC::MarkedSpace::isPagedOut):
  • heap/MarkedSpace.h:
  • runtime/OptionsList.h:

Source/WebKit:

Add mincore to the acceptable syscall list.

  • WebProcess/com.apple.WebProcess.sb.in:

Source/WTF:

Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.

  • wtf/FunctionTraits.h:

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

Location:
branches/safari-611-branch/Source
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-611-branch/Source/JavaScriptCore/ChangeLog

    r276175 r276517  
     12021-04-23  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r276324. rdar://problem/77086404
     4
     5    FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     6    https://bugs.webkit.org/show_bug.cgi?id=224817
     7   
     8    Reviewed by Filip Pizlo.
     9   
     10    Source/JavaScriptCore:
     11   
     12    Right now we try to determine if too many pages are paged out by
     13    dereferencing them and bailing out of the GC if we go over a
     14    deadline. While this works if the only goal is to avoid causing
     15    extensive thrashing on spinny disks (HDD), it doesn't prevent
     16    thrashing when access to disk is fast (e.g. SSD). This is because
     17    on fast disks the proportional time to load the memory from disk
     18    is much lower. Additionally, on SSDs in particular we don't want
     19    to load the pages into RAM then bail as that will force a
     20    different page onto disk, increasing wear.
     21   
     22    This patch switches to asking the OS if each MarkedBlock is paged
     23    out. Then if we are over a threshold we wait until we would have
     24    GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
     25    percentage of "slow" pages (paged out or compressed) needed to
     26    defer the GC. The idea behind that threshold is that if we add
     27    that many pages then the same number of pages would be forced
     28    out of RAM for us to do a GC anyway (in the limit).
     29   
     30    * heap/BlockDirectory.cpp:
     31    (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
     32    (JSC::BlockDirectory::isPagedOut): Deleted.
     33    * heap/BlockDirectory.h:
     34    * heap/FullGCActivityCallback.cpp:
     35    (JSC::FullGCActivityCallback::doCollection):
     36    * heap/Heap.cpp:
     37    (JSC::Heap::isPagedOut):
     38    * heap/Heap.h:
     39    * heap/MarkedSpace.cpp:
     40    (JSC::MarkedSpace::isPagedOut):
     41    * heap/MarkedSpace.h:
     42    * runtime/OptionsList.h:
     43   
     44    Source/WebKit:
     45   
     46    Add mincore to the acceptable syscall list.
     47   
     48    * WebProcess/com.apple.WebProcess.sb.in:
     49   
     50    Source/WTF:
     51   
     52    Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
     53   
     54    * wtf/FunctionTraits.h:
     55   
     56   
     57    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     58
     59    2021-04-20  Keith Miller  <keith_miller@apple.com>
     60
     61            FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     62            https://bugs.webkit.org/show_bug.cgi?id=224817
     63
     64            Reviewed by Filip Pizlo.
     65
     66            Right now we try to determine if too many pages are paged out by
     67            dereferencing them and bailing out of the GC if we go over a
     68            deadline. While this works if the only goal is to avoid causing
     69            extensive thrashing on spinny disks (HDD), it doesn't prevent
     70            thrashing when access to disk is fast (e.g. SSD). This is because
     71            on fast disks the proportional time to load the memory from disk
     72            is much lower. Additionally, on SSDs in particular we don't want
     73            to load the pages into RAM then bail as that will force a
     74            different page onto disk, increasing wear.
     75
     76            This patch switches to asking the OS if each MarkedBlock is paged
     77            out. Then if we are over a threshold we wait until we would have
     78            GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
     79            percentage of "slow" pages (paged out or compressed) needed to
     80            defer the GC. The idea behind that threshold is that if we add
     81            that many pages then the same number of pages would be forced
     82            out of RAM for us to do a GC anyway (in the limit).
     83
     84            * heap/BlockDirectory.cpp:
     85            (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
     86            (JSC::BlockDirectory::isPagedOut): Deleted.
     87            * heap/BlockDirectory.h:
     88            * heap/FullGCActivityCallback.cpp:
     89            (JSC::FullGCActivityCallback::doCollection):
     90            * heap/Heap.cpp:
     91            (JSC::Heap::isPagedOut):
     92            * heap/Heap.h:
     93            * heap/MarkedSpace.cpp:
     94            (JSC::MarkedSpace::isPagedOut):
     95            * heap/MarkedSpace.h:
     96            * runtime/OptionsList.h:
     97
    1982021-04-16  Alan Coon  <alancoon@apple.com>
    299
  • branches/safari-611-branch/Source/JavaScriptCore/heap/BlockDirectory.cpp

    r276175 r276517  
    3232#include "SuperSampler.h"
    3333
     34#include <wtf/FunctionTraits.h>
     35#include <wtf/SimpleStats.h>
     36
    3437namespace JSC {
    3538
     
    5457}
    5558
    56 bool BlockDirectory::isPagedOut(MonotonicTime deadline)
    57 {
    58     unsigned itersSinceLastTimeCheck = 0;
    59     for (auto* block : m_blocks) {
    60         if (block)
    61             block->block().populatePage();
    62         ++itersSinceLastTimeCheck;
    63         if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
    64             MonotonicTime currentTime = MonotonicTime::now();
    65             if (currentTime > deadline)
    66                 return true;
    67             itersSinceLastTimeCheck = 0;
    68         }
    69     }
    70     return false;
     59void BlockDirectory::updatePercentageOfPagedOutPages(SimpleStats& stats)
     60{
     61    // FIXME: We should figure out a solution for Windows.
     62#if OS(UNIX)
     63    size_t pageSize = WTF::pageSize();
     64    ASSERT(!(MarkedBlock::blockSize % pageSize));
     65    auto numberOfPagesInMarkedBlock = MarkedBlock::blockSize / pageSize;
     66    // For some reason this can be unsigned char or char on different OSes...
     67    using MincoreBufferType = std::remove_pointer_t<FunctionTraits<decltype(mincore)>::ArgumentType<2>>;
     68    static_assert(std::is_same_v<std::make_unsigned_t<MincoreBufferType>, unsigned char>);
     69    // pageSize is effectively a constant so this isn't really variable.
     70    IGNORE_CLANG_WARNINGS_BEGIN("vla")
     71    MincoreBufferType pagedBits[numberOfPagesInMarkedBlock];
     72    IGNORE_CLANG_WARNINGS_END
     73
     74    for (auto* handle : m_blocks) {
     75        if (!handle)
     76            continue;
     77
     78        auto markedBlockSizeInBytes = static_cast<size_t>(reinterpret_cast<char*>(handle->end()) - reinterpret_cast<char*>(handle->start()));
     79        RELEASE_ASSERT(markedBlockSizeInBytes / pageSize <= numberOfPagesInMarkedBlock);
     80        // We could cache this in bulk (e.g. 25 MB chunks) but we haven't seen any data that it actually matters.
     81        auto result = mincore(handle->start(), markedBlockSizeInBytes, pagedBits);
     82        RELEASE_ASSERT(!result);
     83        constexpr unsigned pageIsResidentAndNotCompressed = 1;
     84        for (unsigned i = 0; i < numberOfPagesInMarkedBlock; ++i)
     85            stats.add(!(pagedBits[i] & pageIsResidentAndNotCompressed));
     86    }
     87#endif
    7188}
    7289
  • branches/safari-611-branch/Source/JavaScriptCore/heap/BlockDirectory.h

    r276175 r276517  
    3737#include <wtf/SharedTask.h>
    3838#include <wtf/Vector.h>
     39
     40namespace WTF {
     41class SimpleStats;
     42}
    3943
    4044namespace JSC {
     
    8892    void removeBlock(MarkedBlock::Handle*, WillDeleteBlock = WillDeleteBlock::No);
    8993
    90     bool isPagedOut(MonotonicTime deadline);
     94    void updatePercentageOfPagedOutPages(WTF::SimpleStats&);
    9195   
    9296    Lock& bitvectorLock() { return m_bitvectorLock; }
  • branches/safari-611-branch/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp

    r237266 r276517  
    3131namespace JSC {
    3232
    33 #if !PLATFORM(IOS_FAMILY)
    34 const constexpr Seconds pagingTimeOut { 100_ms }; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out.
    35 #endif
    36 
    3733FullGCActivityCallback::FullGCActivityCallback(Heap* heap)
    3834    : GCActivityCallback(heap)
     
    4541    m_didGCRecently = false;
    4642
    47 #if !PLATFORM(IOS_FAMILY)
     43#if !PLATFORM(IOS_FAMILY) || PLATFORM(MACCATALYST)
    4844    MonotonicTime startTime = MonotonicTime::now();
    49     if (heap.isPagedOut(startTime + pagingTimeOut)) {
     45    if (heap.isPagedOut()) {
    5046        cancel();
    51         heap.increaseLastFullGCLength(pagingTimeOut);
     47        heap.increaseLastFullGCLength(MonotonicTime::now() - startTime);
    5248        return;
    5349    }
  • branches/safari-611-branch/Source/JavaScriptCore/heap/Heap.cpp

    r264743 r276517  
    355355}
    356356
    357 bool Heap::isPagedOut(MonotonicTime deadline)
    358 {
    359     return m_objectSpace.isPagedOut(deadline);
     357bool Heap::isPagedOut()
     358{
     359    return m_objectSpace.isPagedOut();
    360360}
    361361
  • branches/safari-611-branch/Source/JavaScriptCore/heap/Heap.h

    r262562 r276517  
    272272
    273273    void didAllocate(size_t);
    274     bool isPagedOut(MonotonicTime deadline);
     274    bool isPagedOut();
    275275   
    276276    const JITStubRoutineSet& jitStubRoutines() { return *m_jitStubRoutines; }
  • branches/safari-611-branch/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r276175 r276517  
    2828#include "MarkedSpaceInlines.h"
    2929#include <wtf/ListDump.h>
     30#include <wtf/SimpleStats.h>
    3031
    3132namespace JSC {
     
    355356}
    356357
    357 bool MarkedSpace::isPagedOut(MonotonicTime deadline)
    358 {
    359     bool result = false;
    360     forEachDirectory(
    361         [&] (BlockDirectory& directory) -> IterationStatus {
    362             if (directory.isPagedOut(deadline)) {
    363                 result = true;
    364                 return IterationStatus::Done;
    365             }
     358bool MarkedSpace::isPagedOut()
     359{
     360    SimpleStats pagedOutPagesStats;
     361
     362    forEachDirectory(
     363        [&] (BlockDirectory& directory) -> IterationStatus {
     364            directory.updatePercentageOfPagedOutPages(pagedOutPagesStats);
    366365            return IterationStatus::Continue;
    367366        });
    368367    // FIXME: Consider taking PreciseAllocations into account here.
    369     return result;
     368    double maxHeapGrowthFactor = VM::isInMiniMode() ? Options::miniVMHeapGrowthFactor() : Options::largeHeapGrowthFactor();
     369    double bailoutPercentage = Options::customFullGCCallbackBailThreshold() == -1.0 ? maxHeapGrowthFactor - 1 : Options::customFullGCCallbackBailThreshold();
     370    return pagedOutPagesStats.mean() > pagedOutPagesStats.count() * bailoutPercentage;
    370371}
    371372
  • branches/safari-611-branch/Source/JavaScriptCore/heap/MarkedSpace.h

    r262786 r276517  
    149149    size_t capacity();
    150150
    151     bool isPagedOut(MonotonicTime deadline);
     151    bool isPagedOut();
    152152   
    153153    HeapVersion markingVersion() const { return m_markingVersion; }
  • branches/safari-611-branch/Source/JavaScriptCore/runtime/OptionsList.h

    r272940 r276517  
    199199    v(Double, miniVMHeapGrowthFactor, 1.27, Normal, nullptr) \
    200200    v(Double, criticalGCMemoryThreshold, 0.80, Normal, "percent memory in use the GC considers critical.  The collector is much more aggressive above this threshold") \
     201    v(Double, customFullGCCallbackBailThreshold, -1.0, Normal, "percent of memory paged out before we bail out of timer based Full GCs. -1.0 means use (maxHeapGrowthFactor - 1)") \
    201202    v(Double, minimumMutatorUtilization, 0, Normal, nullptr) \
    202203    v(Double, maximumMutatorUtilization, 0.7, Normal, nullptr) \
  • branches/safari-611-branch/Source/WTF/ChangeLog

    r276063 r276517  
     12021-04-23  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r276324. rdar://problem/77086404
     4
     5    FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     6    https://bugs.webkit.org/show_bug.cgi?id=224817
     7   
     8    Reviewed by Filip Pizlo.
     9   
     10    Source/JavaScriptCore:
     11   
     12    Right now we try to determine if too many pages are paged out by
     13    dereferencing them and bailing out of the GC if we go over a
     14    deadline. While this works if the only goal is to avoid causing
     15    extensive thrashing on spinny disks (HDD), it doesn't prevent
     16    thrashing when access to disk is fast (e.g. SSD). This is because
     17    on fast disks the proportional time to load the memory from disk
     18    is much lower. Additionally, on SSDs in particular we don't want
     19    to load the pages into RAM then bail as that will force a
     20    different page onto disk, increasing wear.
     21   
     22    This patch switches to asking the OS if each MarkedBlock is paged
     23    out. Then if we are over a threshold we wait until we would have
     24    GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
     25    percentage of "slow" pages (paged out or compressed) needed to
     26    defer the GC. The idea behind that threshold is that if we add
     27    that many pages then the same number of pages would be forced
     28    out of RAM for us to do a GC anyway (in the limit).
     29   
     30    * heap/BlockDirectory.cpp:
     31    (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
     32    (JSC::BlockDirectory::isPagedOut): Deleted.
     33    * heap/BlockDirectory.h:
     34    * heap/FullGCActivityCallback.cpp:
     35    (JSC::FullGCActivityCallback::doCollection):
     36    * heap/Heap.cpp:
     37    (JSC::Heap::isPagedOut):
     38    * heap/Heap.h:
     39    * heap/MarkedSpace.cpp:
     40    (JSC::MarkedSpace::isPagedOut):
     41    * heap/MarkedSpace.h:
     42    * runtime/OptionsList.h:
     43   
     44    Source/WebKit:
     45   
     46    Add mincore to the acceptable syscall list.
     47   
     48    * WebProcess/com.apple.WebProcess.sb.in:
     49   
     50    Source/WTF:
     51   
     52    Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
     53   
     54    * wtf/FunctionTraits.h:
     55   
     56   
     57    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     58
     59    2021-04-20  Keith Miller  <keith_miller@apple.com>
     60
     61            FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     62            https://bugs.webkit.org/show_bug.cgi?id=224817
     63
     64            Reviewed by Filip Pizlo.
     65
     66            Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
     67
     68            * wtf/FunctionTraits.h:
     69
    1702021-04-08  Russell Epstein  <repstein@apple.com>
    271
  • branches/safari-611-branch/Source/WTF/wtf/FunctionTraits.h

    r233504 r276517  
    8181};
    8282
     83template<typename Result, typename... Args>
     84struct FunctionTraits<Result(Args...) noexcept> : public FunctionTraits<Result(Args...)> {
     85};
     86
     87template<typename Result, typename... Args>
     88struct FunctionTraits<Result(*)(Args...) noexcept> : public FunctionTraits<Result(Args...)> {
     89};
     90
    8391} // namespace WTF
    8492
  • branches/safari-611-branch/Source/WebKit/ChangeLog

    r276501 r276517  
     12021-04-23  Russell Epstein  <repstein@apple.com>
     2
     3        Cherry-pick r276324. rdar://problem/77086404
     4
     5    FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     6    https://bugs.webkit.org/show_bug.cgi?id=224817
     7   
     8    Reviewed by Filip Pizlo.
     9   
     10    Source/JavaScriptCore:
     11   
     12    Right now we try to determine if too many pages are paged out by
     13    dereferencing them and bailing out of the GC if we go over a
     14    deadline. While this works if the only goal is to avoid causing
     15    extensive thrashing on spinny disks (HDD), it doesn't prevent
     16    thrashing when access to disk is fast (e.g. SSD). This is because
     17    on fast disks the proportional time to load the memory from disk
     18    is much lower. Additionally, on SSDs in particular we don't want
     19    to load the pages into RAM then bail as that will force a
     20    different page onto disk, increasing wear.
     21   
     22    This patch switches to asking the OS if each MarkedBlock is paged
     23    out. Then if we are over a threshold we wait until we would have
     24    GC'd anyway. This patch uses the (maxVMGrowthFactor - 1) as the
     25    percentage of "slow" pages (paged out or compressed) needed to
     26    defer the GC. The idea behind that threshold is that if we add
     27    that many pages then the same number of pages would be forced
     28    out of RAM for us to do a GC anyway (in the limit).
     29   
     30    * heap/BlockDirectory.cpp:
     31    (JSC::BlockDirectory::updatePercentageOfPagedOutPages):
     32    (JSC::BlockDirectory::isPagedOut): Deleted.
     33    * heap/BlockDirectory.h:
     34    * heap/FullGCActivityCallback.cpp:
     35    (JSC::FullGCActivityCallback::doCollection):
     36    * heap/Heap.cpp:
     37    (JSC::Heap::isPagedOut):
     38    * heap/Heap.h:
     39    * heap/MarkedSpace.cpp:
     40    (JSC::MarkedSpace::isPagedOut):
     41    * heap/MarkedSpace.h:
     42    * runtime/OptionsList.h:
     43   
     44    Source/WebKit:
     45   
     46    Add mincore to the acceptable syscall list.
     47   
     48    * WebProcess/com.apple.WebProcess.sb.in:
     49   
     50    Source/WTF:
     51   
     52    Add a noexcept flavor of FunctionTraits. On Linux mincore (and probably other syscalls) are marked noexcept so the existing overloads don't work.
     53   
     54    * wtf/FunctionTraits.h:
     55   
     56   
     57    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276324 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     58
     59    2021-04-20  Keith Miller  <keith_miller@apple.com>
     60
     61            FullGCActivityCallback should use the percentage of pages uncompressed in RAM to determine deferral.
     62            https://bugs.webkit.org/show_bug.cgi?id=224817
     63
     64            Reviewed by Filip Pizlo.
     65
     66            Add mincore to the acceptable syscall list.
     67
     68            * WebProcess/com.apple.WebProcess.sb.in:
     69
    1702021-04-23  Russell Epstein  <repstein@apple.com>
    271
  • branches/safari-611-branch/Source/WebKit/WebProcess/com.apple.WebProcess.sb.in

    r276400 r276517  
    15161516        (syscall-number SYS_mprotect)
    15171517        (syscall-number SYS_madvise)
     1518        (syscall-number SYS_mincore)
    15181519        (syscall-number SYS_fcntl)
    15191520        (syscall-number SYS_select)
Note: See TracChangeset for help on using the changeset viewer.