Skip to content
Permalink
Browse files
[macOS] Policy for warning about or killing processes using too much …
…memory triggers too easily

https://bugs.webkit.org/show_bug.cgi?id=221104
<rdar://73625621>

Reviewed by Geoff Garen.

The policy for warning about or killing processes using too much memory was triggering too
easily. I made the following changes to the policy to address this:
1. We no longer kill WebProcesses associated with a visible (parented) view under any
   circumstances. We used to kill active WebProcesses when they reached 4GB. We would
   also kill visible WebProcesses when they reached 2GB if there were visible but not
   active / focused.
2. For background WebProcesses (associated with non visible / parented views), I have
   raised the kill limit from 2GB to 4GB.
3. For foreground WebProcesses (associated with visible / parent views), I have also
   raised the limit to show the excessive memory usage banner from 2GB to 4GB.

Source/WebCore:

* page/PerformanceMonitor.cpp:
(WebCore::PerformanceMonitor::activityStateChanged):

Source/WTF:

* wtf/MemoryPressureHandler.cpp:
(WTF::thresholdForMemoryKillOfInactiveProcess):
(WTF::MemoryPressureHandler::thresholdForMemoryKill):
(WTF::MemoryPressureHandler::shrinkOrDie):
(WTF::MemoryPressureHandler::measurementTimerFired):
* wtf/MemoryPressureHandler.h:


Canonical link: https://commits.webkit.org/233465@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272046 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Jan 29, 2021
1 parent b435e75 commit dbed638e9975b00d206546a3f0294db75ff0f0c0
Showing 5 changed files with 69 additions and 17 deletions.
@@ -1,3 +1,29 @@
2021-01-28 Chris Dumez <cdumez@apple.com>

[macOS] Policy for warning about or killing processes using too much memory triggers too easily
https://bugs.webkit.org/show_bug.cgi?id=221104
<rdar://73625621>

Reviewed by Geoff Garen.

The policy for warning about or killing processes using too much memory was triggering too
easily. I made the following changes to the policy to address this:
1. We no longer kill WebProcesses associated with a visible (parented) view under any
circumstances. We used to kill active WebProcesses when they reached 4GB. We would
also kill visible WebProcesses when they reached 2GB if there were visible but not
active / focused.
2. For background WebProcesses (associated with non visible / parented views), I have
raised the kill limit from 2GB to 4GB.
3. For foreground WebProcesses (associated with visible / parent views), I have also
raised the limit to show the excessive memory usage banner from 2GB to 4GB.

* wtf/MemoryPressureHandler.cpp:
(WTF::thresholdForMemoryKillOfInactiveProcess):
(WTF::MemoryPressureHandler::thresholdForMemoryKill):
(WTF::MemoryPressureHandler::shrinkOrDie):
(WTF::MemoryPressureHandler::measurementTimerFired):
* wtf/MemoryPressureHandler.h:

2021-01-28 Yusuke Suzuki <ysuzuki@apple.com>

[JSC] Add JSC_SIGNAL_FOR_GC environment variable for Linux / FreeBSD
@@ -96,17 +96,14 @@ static const char* toString(MemoryUsagePolicy policy)
}
#endif

static size_t thresholdForMemoryKillWithProcessState(WebsamProcessState processState, unsigned tabCount)
static size_t thresholdForMemoryKillOfInactiveProcess(unsigned tabCount)
{
size_t baseThreshold = 2 * GB;
#if CPU(X86_64) || CPU(ARM64)
if (processState == WebsamProcessState::Active)
baseThreshold = 4 * GB;
size_t baseThreshold = 4 * GB;
if (tabCount > 1)
baseThreshold += std::min(tabCount - 1, 4u) * 1 * GB;
#else
if ((tabCount > 1) || (processState == WebsamProcessState::Active))
baseThreshold = 3 * GB;
size_t baseThreshold = tabCount > 1 ? 3 * GB : 2 * GB;
#endif
return std::min(baseThreshold, static_cast<size_t>(ramSize() * 0.9));
}
@@ -118,9 +115,15 @@ void MemoryPressureHandler::setPageCount(unsigned pageCount)
singleton().m_pageCount = pageCount;
}

size_t MemoryPressureHandler::thresholdForMemoryKill()
Optional<size_t> MemoryPressureHandler::thresholdForMemoryKill()
{
return thresholdForMemoryKillWithProcessState(m_processState, m_pageCount);
switch (m_processState) {
case WebsamProcessState::Inactive:
return thresholdForMemoryKillOfInactiveProcess(m_pageCount);
case WebsamProcessState::Active:
break;
}
return WTF::nullopt;
}

static size_t thresholdForPolicy(MemoryUsagePolicy policy)
@@ -162,21 +165,21 @@ MemoryUsagePolicy MemoryPressureHandler::currentMemoryUsagePolicy()
return policyForFootprint(memoryFootprint());
}

void MemoryPressureHandler::shrinkOrDie()
void MemoryPressureHandler::shrinkOrDie(size_t killThreshold)
{
RELEASE_LOG(MemoryPressure, "Process is above the memory kill threshold. Trying to shrink down.");
releaseMemory(Critical::Yes, Synchronous::Yes);

size_t footprint = memoryFootprint();
RELEASE_LOG(MemoryPressure, "New memory footprint: %zu MB", footprint / MB);

if (footprint < thresholdForMemoryKill()) {
if (footprint < killThreshold) {
RELEASE_LOG(MemoryPressure, "Shrank below memory kill threshold. Process gets to live.");
setMemoryUsagePolicyBasedOnFootprint(footprint);
return;
}

WTFLogAlways("Unable to shrink memory footprint of process (%zu MB) below the kill thresold (%zu MB). Killed\n", footprint / MB, thresholdForMemoryKill() / MB);
WTFLogAlways("Unable to shrink memory footprint of process (%zu MB) below the kill thresold (%zu MB). Killed\n", footprint / MB, killThreshold / MB);
RELEASE_ASSERT(m_memoryKillCallback);
m_memoryKillCallback();
}
@@ -198,8 +201,9 @@ void MemoryPressureHandler::measurementTimerFired()
#if PLATFORM(COCOA)
RELEASE_LOG(MemoryPressure, "Current memory footprint: %zu MB", footprint / MB);
#endif
if (footprint >= thresholdForMemoryKill()) {
shrinkOrDie();
auto killThreshold = thresholdForMemoryKill();
if (killThreshold && footprint >= *killThreshold) {
shrinkOrDie(*killThreshold);
return;
}

@@ -216,7 +220,7 @@ void MemoryPressureHandler::measurementTimerFired()
break;
}

if (processState() == WebsamProcessState::Active && footprint > thresholdForMemoryKillWithProcessState(WebsamProcessState::Inactive, m_pageCount))
if (processState() == WebsamProcessState::Active && footprint > thresholdForMemoryKillOfInactiveProcess(m_pageCount))
doesExceedInactiveLimitWhileActive();
else
doesNotExceedInactiveLimitWhileActive();
@@ -156,7 +156,7 @@ class MemoryPressureHandler {
void setShouldLogMemoryMemoryPressureEvents(bool shouldLog) { m_shouldLogMemoryMemoryPressureEvents = shouldLog; }

private:
size_t thresholdForMemoryKill();
Optional<size_t> thresholdForMemoryKill();
void memoryPressureStatusChanged();

void uninstall();
@@ -171,7 +171,7 @@ class MemoryPressureHandler {
void platformInitialize();

void measurementTimerFired();
void shrinkOrDie();
void shrinkOrDie(size_t killThreshold);
void setMemoryUsagePolicyBasedOnFootprint(size_t);
void doesExceedInactiveLimitWhileActive();
void doesNotExceedInactiveLimitWhileActive();
@@ -1,3 +1,25 @@
2021-01-28 Chris Dumez <cdumez@apple.com>

[macOS] Policy for warning about or killing processes using too much memory triggers too easily
https://bugs.webkit.org/show_bug.cgi?id=221104
<rdar://73625621>

Reviewed by Geoff Garen.

The policy for warning about or killing processes using too much memory was triggering too
easily. I made the following changes to the policy to address this:
1. We no longer kill WebProcesses associated with a visible (parented) view under any
circumstances. We used to kill active WebProcesses when they reached 4GB. We would
also kill visible WebProcesses when they reached 2GB if there were visible but not
active / focused.
2. For background WebProcesses (associated with non visible / parented views), I have
raised the kill limit from 2GB to 4GB.
3. For foreground WebProcesses (associated with visible / parent views), I have also
raised the limit to show the excessive memory usage banner from 2GB to 4GB.

* page/PerformanceMonitor.cpp:
(WebCore::PerformanceMonitor::activityStateChanged):

2021-01-28 Myles C. Maxfield <mmaxfield@apple.com>

Remove some uses of FontSelector from within CSSFontFace
@@ -131,7 +131,7 @@ void PerformanceMonitor::activityStateChanged(OptionSet<ActivityState::Flag> old
m_postBackgroundingMemoryUsageTimer.startOneShot(memoryUsageMeasurementDelay);
}

if (newState.containsAll({ ActivityState::IsVisible, ActivityState::WindowIsActive })) {
if (newState.contains(ActivityState::IsVisible)) {
m_processMayBecomeInactive = false;
m_processMayBecomeInactiveTimer.stop();
} else if (!m_processMayBecomeInactive && !m_processMayBecomeInactiveTimer.isActive())

0 comments on commit dbed638

Please sign in to comment.