Title: [210964] branches/safari-603-branch/Source
Revision
210964
Author
matthew_han...@apple.com
Date
2017-01-20 08:56:17 -0800 (Fri, 20 Jan 2017)

Log Message

Merge r210936. rdar://problem/30058349

Modified Paths

Added Paths

Diff

Modified: branches/safari-603-branch/Source/WebCore/CMakeLists.txt (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/CMakeLists.txt	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/CMakeLists.txt	2017-01-20 16:56:17 UTC (rev 210964)
@@ -2059,6 +2059,7 @@
     page/Performance.cpp
     page/PerformanceEntry.cpp
     page/PerformanceLogging.cpp
+    page/PerformanceMonitor.cpp
     page/PerformanceNavigation.cpp
     page/PerformanceResourceTiming.cpp
     page/PerformanceTiming.cpp

Modified: branches/safari-603-branch/Source/WebCore/ChangeLog (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/ChangeLog	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/ChangeLog	2017-01-20 16:56:17 UTC (rev 210964)
@@ -1,5 +1,59 @@
 2017-01-20  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210936. rdar://problem/30058349
+
+    2017-01-19  Chris Dumez  <cdu...@apple.com>
+
+            Implement per activity state CPU usage reporting using diagnostic logging
+            https://bugs.webkit.org/show_bug.cgi?id=167163
+            <rdar://problem/30058349>
+
+            Reviewed by Andreas Kling.
+
+            Implement per activity state CPU usage reporting using diagnostic logging.
+
+            * WebCore.xcodeproj/project.pbxproj:
+            * page/ActivityState.h:
+            * page/ChromeClient.h:
+            * page/DiagnosticLoggingKeys.cpp:
+            (WebCore::DiagnosticLoggingKeys::nonVisibleStateKey):
+            (WebCore::DiagnosticLoggingKeys::visibleNonActiveStateKey):
+            (WebCore::DiagnosticLoggingKeys::visibleAndActiveStateKey):
+            (WebCore::DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLogginKey):
+            (WebCore::DiagnosticLoggingKeys::backgroundCPUUsageToDiagnosticLogginKey):
+            * page/DiagnosticLoggingKeys.h:
+            * page/Page.cpp:
+            (WebCore::isUtilityPageChromeClient):
+            (WebCore::Page::Page):
+            (WebCore::Page::~Page):
+            (WebCore::Page::didStartProvisionalLoad):
+            (WebCore::Page::didFinishLoad):
+            (WebCore::Page::isUtilityPage):
+            (WebCore::Page::setActivityState):
+            (WebCore::Page::setIsVisibleInternal):
+            * page/Page.h:
+            (WebCore::Page::activityState):
+            (WebCore::Page::isUtilityPage):
+            * page/PerformanceMonitor.cpp: Added.
+            (WebCore::activityStateForCPUSampling):
+            (WebCore::PerformanceMonitor::PerformanceMonitor):
+            (WebCore::PerformanceMonitor::didStartProvisionalLoad):
+            (WebCore::PerformanceMonitor::didFinishLoad):
+            (WebCore::PerformanceMonitor::activityStateChanged):
+            (WebCore::PerformanceMonitor::measurePostLoadCPUUsage):
+            (WebCore::PerformanceMonitor::measurePostBackgroundingCPUUsage):
+            (WebCore::PerformanceMonitor::measurePerActivityStateCPUUsage):
+            (WebCore::stringForCPUSamplingActivityState):
+            (WebCore::PerformanceMonitor::measureCPUUsageInActivityState):
+            * page/PerformanceMonitor.h: Copied from Source/WebCore/page/ActivityState.h.
+            * page/Settings.cpp:
+            * page/Settings.h:
+            (WebCore::Settings::isPostLoadCPUUsageMeasurementEnabled):
+            (WebCore::Settings::isPostBackgroundingCPUUsageMeasurementEnabled):
+            (WebCore::Settings::isPerActivityStateCPUUsageMeasurementEnabled):
+
+2017-01-20  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r210473. rdar://problem/29204422
 
     2017-01-06  Jer Noble  <jer.no...@apple.com>

Modified: branches/safari-603-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-01-20 16:56:17 UTC (rev 210964)
@@ -3073,6 +3073,8 @@
 		83F1206B1B8C104700D75F63 /* JSNodeFilterCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83F1206A1B8C103600D75F63 /* JSNodeFilterCustom.cpp */; };
 		83FE7CA71DA9F1A70037237C /* UIEventInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE7CA41DA9F1660037237C /* UIEventInit.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		83FE7CA81DA9F1B60037237C /* EventModifierInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE7CA31DA9F1650037237C /* EventModifierInit.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		83FE90271E307C30003E9199 /* PerformanceMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE90261E307C1C003E9199 /* PerformanceMonitor.h */; };
+		83FE90281E307C33003E9199 /* PerformanceMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83FE90251E307C1C003E9199 /* PerformanceMonitor.cpp */; };
 		8419D2A7120D92D000141F8F /* SVGPathByteStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 8419D2A4120D92D000141F8F /* SVGPathByteStream.h */; };
 		8419D2A8120D92D000141F8F /* SVGPathByteStreamBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8419D2A5120D92D000141F8F /* SVGPathByteStreamBuilder.cpp */; };
 		8419D2A9120D92D000141F8F /* SVGPathByteStreamBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8419D2A6120D92D000141F8F /* SVGPathByteStreamBuilder.h */; };
@@ -10626,6 +10628,8 @@
 		83FE7CA41DA9F1660037237C /* UIEventInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIEventInit.h; sourceTree = "<group>"; };
 		83FE7CA51DA9F1660037237C /* UIEventInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = UIEventInit.idl; sourceTree = "<group>"; };
 		83FE7CA61DA9F1660037237C /* EventModifierInit.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EventModifierInit.idl; sourceTree = "<group>"; };
+		83FE90251E307C1C003E9199 /* PerformanceMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PerformanceMonitor.cpp; sourceTree = "<group>"; };
+		83FE90261E307C1C003E9199 /* PerformanceMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceMonitor.h; sourceTree = "<group>"; };
 		8419D2A4120D92D000141F8F /* SVGPathByteStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPathByteStream.h; sourceTree = "<group>"; };
 		8419D2A5120D92D000141F8F /* SVGPathByteStreamBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGPathByteStreamBuilder.cpp; sourceTree = "<group>"; };
 		8419D2A6120D92D000141F8F /* SVGPathByteStreamBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPathByteStreamBuilder.h; sourceTree = "<group>"; };
@@ -18057,6 +18061,8 @@
 				86BE33FC15058CB200CE0FD8 /* PerformanceEntry.idl */,
 				AD5A0C211DECA10100707054 /* PerformanceLogging.cpp */,
 				AD5A0C201DECA0B500707054 /* PerformanceLogging.h */,
+				83FE90251E307C1C003E9199 /* PerformanceMonitor.cpp */,
+				83FE90261E307C1C003E9199 /* PerformanceMonitor.h */,
 				8AF4E55211DC5A36000ED3DE /* PerformanceNavigation.cpp */,
 				8AF4E55311DC5A36000ED3DE /* PerformanceNavigation.h */,
 				8AF4E55411DC5A36000ED3DE /* PerformanceNavigation.idl */,
@@ -26752,6 +26758,7 @@
 				85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */,
 				1AE00D59182DAC8D00087DD7 /* KeyedCoding.h in Headers */,
 				517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */,
+				83FE90271E307C30003E9199 /* PerformanceMonitor.h in Headers */,
 				517A63C61B74319200E7DCDC /* KeyedEncoderCF.h in Headers */,
 				A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */,
 				265541391489811C000DFC5D /* KeyEventCodesIOS.h in Headers */,
@@ -31178,6 +31185,7 @@
 				073BE34E17D180B2002BD431 /* RTCSessionDescriptionDescriptor.cpp in Sources */,
 				078E090E17D14CEE00420AA1 /* RTCStatsReport.cpp in Sources */,
 				078E091017D14CEE00420AA1 /* RTCStatsResponse.cpp in Sources */,
+				83FE90281E307C33003E9199 /* PerformanceMonitor.cpp in Sources */,
 				5E2C43671BCEE3770001E2BC /* RTCTrackEvent.cpp in Sources */,
 				5824ABA21AE81116009074B7 /* RubyElement.cpp in Sources */,
 				5824ABA61AE81384009074B7 /* RubyTextElement.cpp in Sources */,

Modified: branches/safari-603-branch/Source/WebCore/page/ActivityState.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/ActivityState.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/ActivityState.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -45,4 +45,10 @@
     static const Flags AllFlags = WindowIsActive | IsFocused | IsVisible | IsVisibleOrOccluded | IsInWindow | IsVisuallyIdle | IsAudible | IsLoading;
 };
 
+enum class ActivityStateForCPUSampling {
+    NonVisible,
+    VisibleNonActive,
+    VisibleAndActive
+};
+
 } // namespace WebCore

Modified: branches/safari-603-branch/Source/WebCore/page/ChromeClient.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/ChromeClient.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/ChromeClient.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -21,6 +21,7 @@
 
 #pragma once
 
+#include "ActivityState.h"
 #include "AXObjectCache.h"
 #include "Cursor.h"
 #include "DatabaseDetails.h"
@@ -460,6 +461,8 @@
 
     virtual void didInvalidateDocumentMarkerRects() { }
 
+    virtual void reportProcessCPUTime(int64_t, ActivityStateForCPUSampling) { }
+
 protected:
     virtual ~ChromeClient() { }
 };

Modified: branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.cpp (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.cpp	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -163,6 +163,11 @@
     return ASCIILiteral("noStore");
 }
 
+String DiagnosticLoggingKeys::nonVisibleStateKey()
+{
+    return ASCIILiteral("nonVisibleState");
+}
+
 String DiagnosticLoggingKeys::notInMemoryCacheKey()
 {
     return ASCIILiteral("notInMemoryCache");
@@ -598,6 +603,16 @@
     return ASCIILiteral("video");
 }
 
+String DiagnosticLoggingKeys::visibleNonActiveStateKey()
+{
+    return ASCIILiteral("visibleNonActiveState");
+}
+
+String DiagnosticLoggingKeys::visibleAndActiveStateKey()
+{
+    return ASCIILiteral("visibleAndActiveState");
+}
+
 String DiagnosticLoggingKeys::wastedSpeculativeWarmupWithRevalidationKey()
 {
     return ASCIILiteral("wastedSpeculativeWarmupWithRevalidation");
@@ -658,5 +673,37 @@
     return ASCIILiteral("webGL");
 }
 
+String DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLoggingKey(double cpuUsage)
+{
+    if (cpuUsage < 10)
+        return ASCIILiteral("Below10");
+    if (cpuUsage < 20)
+        return ASCIILiteral("10to20");
+    if (cpuUsage < 40)
+        return ASCIILiteral("20to40");
+    if (cpuUsage < 60)
+        return ASCIILiteral("40to60");
+    if (cpuUsage < 80)
+        return ASCIILiteral("60to80");
+    return ASCIILiteral("over80");
+}
+
+String DiagnosticLoggingKeys::backgroundCPUUsageToDiagnosticLoggingKey(double cpuUsage)
+{
+    if (cpuUsage < 1)
+        return ASCIILiteral("Below1");
+    if (cpuUsage < 5)
+        return ASCIILiteral("1to5");
+    if (cpuUsage < 10)
+        return ASCIILiteral("5to10");
+    if (cpuUsage < 30)
+        return ASCIILiteral("10to30");
+    if (cpuUsage < 50)
+        return ASCIILiteral("30to50");
+    if (cpuUsage < 70)
+        return ASCIILiteral("50to70");
+    return ASCIILiteral("over70");
+}
+
 } // namespace WebCore
 

Modified: branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/DiagnosticLoggingKeys.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -40,7 +40,7 @@
     static String cachedResourceRevalidationKey();
     static String canCacheKey();
     static String cannotSuspendActiveDOMObjectsKey();
-    static String cpuUsageKey();
+    WEBCORE_EXPORT static String cpuUsageKey();
     WEBCORE_EXPORT static String createSharedBufferFailedKey();
     WEBCORE_EXPORT static String deltaKey();
     static String deniedByClientKey();
@@ -88,6 +88,7 @@
     static String noDocumentLoaderKey();
     WEBCORE_EXPORT static String noLongerInCacheKey();
     static String noStoreKey();
+    WEBCORE_EXPORT static String nonVisibleStateKey();
     WEBCORE_EXPORT static String notHTTPFamilyKey();
     WEBCORE_EXPORT static String notInCacheKey();
     static String notInMemoryCacheKey();
@@ -150,6 +151,8 @@
     WEBCORE_EXPORT static String userKey();
     WEBCORE_EXPORT static String varyingHeaderMismatchKey();
     static String videoKey();
+    WEBCORE_EXPORT static String visibleNonActiveStateKey();
+    WEBCORE_EXPORT static String visibleAndActiveStateKey();
     WEBCORE_EXPORT static String wastedSpeculativeWarmupWithRevalidationKey();
     WEBCORE_EXPORT static String wastedSpeculativeWarmupWithoutRevalidationKey();
     WEBCORE_EXPORT static String webGLKey();
@@ -156,6 +159,9 @@
     WEBCORE_EXPORT static String webViewKey();
     WEBCORE_EXPORT static String zoomedKey();
 
+    WEBCORE_EXPORT static String foregroundCPUUsageToDiagnosticLoggingKey(double cpuUsage);
+    WEBCORE_EXPORT static String backgroundCPUUsageToDiagnosticLoggingKey(double cpuUsage);
+
     // Success / Failure keys.
     static String successKey();
     static String failureKey();

Modified: branches/safari-603-branch/Source/WebCore/page/Page.cpp (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/Page.cpp	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/Page.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -66,6 +66,7 @@
 #include "PageDebuggable.h"
 #include "PageGroup.h"
 #include "PageOverlayController.h"
+#include "PerformanceMonitor.h"
 #include "PlatformMediaSessionManager.h"
 #include "PlugInClient.h"
 #include "PluginData.h"
@@ -126,13 +127,13 @@
 
 namespace WebCore {
 
-#define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - Page::" fmt, this, ##__VA_ARGS__)
-
 static HashSet<Page*>* allPages;
+static unsigned nonUtilityPageCount { 0 };
 
-static const std::chrono::seconds cpuUsageMeasurementDelay { 5 };
-static const std::chrono::seconds postLoadCPUUsageMeasurementDuration { 10 };
-static const std::chrono::minutes backgroundCPUUsageMeasurementDuration { 5 };
+static inline bool isUtilityPageChromeClient(ChromeClient& chromeClient)
+{
+    return chromeClient.isEmptyChromeClient() || chromeClient.isSVGImageChromeClient();
+}
 
 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
 
@@ -252,8 +253,8 @@
     , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
     , m_sessionID(SessionID::defaultSessionID())
     , m_isClosing(false)
-    , m_postPageLoadCPUUsageTimer(*this, &Page::measurePostLoadCPUUsage)
-    , m_postBackgroundingCPUUsageTimer(*this, &Page::measurePostBackgroundingCPUUsage)
+    , m_isUtilityPage(isUtilityPageChromeClient(chrome().client()))
+    , m_performanceMonitor(isUtilityPage() ? nullptr : std::make_unique<PerformanceMonitor>(*this))
 {
     updateTimerThrottlingState();
 
@@ -270,6 +271,8 @@
 
     ASSERT(!allPages->contains(this));
     allPages->add(this);
+    if (!isUtilityPage())
+        ++nonUtilityPageCount;
 
 #ifndef NDEBUG
     pageCounter.increment();
@@ -294,6 +297,8 @@
     m_mainFrame->setView(nullptr);
     setGroupName(String());
     allPages->remove(this);
+    if (!isUtilityPage())
+        --nonUtilityPageCount;
     
     m_settings->pageDestroyed();
 
@@ -937,8 +942,8 @@
 
 void Page::didStartProvisionalLoad()
 {
-    m_postLoadCPUTime = std::nullopt;
-    m_postPageLoadCPUUsageTimer.stop();
+    if (m_performanceMonitor)
+        m_performanceMonitor->didStartProvisionalLoad();
 }
 
 void Page::didFinishLoad()
@@ -945,85 +950,15 @@
 {
     resetRelevantPaintedObjectCounter();
 
-    // Only do post-load CPU usage measurement if there is a single Page in the process in order to reduce noise.
-    if (Settings::isPostLoadCPUUsageMeasurementEnabled() && allPages->size() == 1) {
-        m_postLoadCPUTime = std::nullopt;
-        m_postPageLoadCPUUsageTimer.startOneShot(cpuUsageMeasurementDelay);
-    }
+    if (m_performanceMonitor)
+        m_performanceMonitor->didFinishLoad();
 }
 
-static String foregroundCPUUsageToDiagnosticLogginKey(double cpuUsage)
+bool Page::isOnlyNonUtilityPage() const
 {
-    if (cpuUsage < 10)
-        return ASCIILiteral("Below10");
-    if (cpuUsage < 20)
-        return ASCIILiteral("10to20");
-    if (cpuUsage < 40)
-        return ASCIILiteral("20to40");
-    if (cpuUsage < 60)
-        return ASCIILiteral("40to60");
-    if (cpuUsage < 80)
-        return ASCIILiteral("60to80");
-    return ASCIILiteral("over80");
+    return !isUtilityPage() && nonUtilityPageCount == 1;
 }
 
-void Page::measurePostLoadCPUUsage()
-{
-    if (allPages->size() != 1)
-        return;
-
-    if (!m_postLoadCPUTime) {
-        m_postLoadCPUTime = getCPUTime();
-        if (m_postLoadCPUTime)
-            m_postPageLoadCPUUsageTimer.startOneShot(postLoadCPUUsageMeasurementDuration);
-        return;
-    }
-    std::optional<CPUTime> cpuTime = getCPUTime();
-    if (!cpuTime)
-        return;
-
-    double cpuUsage = cpuTime.value().percentageCPUUsageSince(*m_postLoadCPUTime);
-    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostLoadCPUUsage: Process was using %.1f%% percent CPU after the page load.", cpuUsage);
-    diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageLoadKey(), DiagnosticLoggingKeys::cpuUsageKey(), foregroundCPUUsageToDiagnosticLogginKey(cpuUsage), ShouldSample::No);
-}
-
-static String backgroundCPUUsageToDiagnosticLogginKey(double cpuUsage)
-{
-    if (cpuUsage < 1)
-        return ASCIILiteral("Below1");
-    if (cpuUsage < 5)
-        return ASCIILiteral("1to5");
-    if (cpuUsage < 10)
-        return ASCIILiteral("5to10");
-    if (cpuUsage < 30)
-        return ASCIILiteral("10to30");
-    if (cpuUsage < 50)
-        return ASCIILiteral("30to50");
-    if (cpuUsage < 70)
-        return ASCIILiteral("50to70");
-    return ASCIILiteral("over70");
-}
-
-void Page::measurePostBackgroundingCPUUsage()
-{
-    if (allPages->size() != 1)
-        return;
-
-    if (!m_postBackgroundingCPUTime) {
-        m_postBackgroundingCPUTime = getCPUTime();
-        if (m_postBackgroundingCPUTime)
-            m_postBackgroundingCPUUsageTimer.startOneShot(backgroundCPUUsageMeasurementDuration);
-        return;
-    }
-    std::optional<CPUTime> cpuTime = getCPUTime();
-    if (!cpuTime)
-        return;
-
-    double cpuUsage = cpuTime.value().percentageCPUUsageSince(*m_postBackgroundingCPUTime);
-    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostBackgroundingCPUUsage: Process was using %.1f%% percent CPU after becoming non visible.", cpuUsage);
-    diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageBackgroundingKey(), DiagnosticLoggingKeys::cpuUsageKey(), backgroundCPUUsageToDiagnosticLogginKey(cpuUsage), ShouldSample::No);
-}
-
 void Page::setTopContentInset(float contentInset)
 {
     if (m_topContentInset == contentInset)
@@ -1576,6 +1511,9 @@
 
     if (wasVisibleAndActive != isVisibleAndActive())
         PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary();
+
+    if (m_performanceMonitor)
+        m_performanceMonitor->activityStateChanged(oldActivityState, activityState);
 }
 
 bool Page::isVisibleAndActive() const
@@ -1632,13 +1570,6 @@
         if (FrameView* view = mainFrame().view())
             view->hide();
     }
-
-    // Measure CPU usage of pages when they are no longer visible.
-    m_postBackgroundingCPUTime = std::nullopt;
-    if (isVisible)
-        m_postBackgroundingCPUUsageTimer.stop();
-    else if (Settings::isPostBackgroundingCPUUsageMeasurementEnabled() && allPages->size() == 1)
-        m_postBackgroundingCPUUsageTimer.startOneShot(cpuUsageMeasurementDelay);
 }
 
 void Page::setIsPrerender()

Modified: branches/safari-603-branch/Source/WebCore/page/Page.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/Page.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/Page.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -21,7 +21,6 @@
 #pragma once
 
 #include "ActivityState.h"
-#include "CPUTime.h"
 #include "FindOptions.h"
 #include "FrameLoaderTypes.h"
 #include "LayoutMilestones.h"
@@ -105,6 +104,7 @@
 class PageConsoleClient;
 class PageDebuggable;
 class PageGroup;
+class PerformanceMonitor;
 class PlugInClient;
 class PluginData;
 class PluginInfoProvider;
@@ -357,6 +357,8 @@
 
     // Notifications when the Page starts and stops being presented via a native window.
     WEBCORE_EXPORT void setActivityState(ActivityState::Flags);
+    ActivityState::Flags activityState() const { return m_activityState; }
+
     bool isVisibleAndActive() const;
     WEBCORE_EXPORT void setIsVisible(bool);
     WEBCORE_EXPORT void setIsPrerender();
@@ -559,6 +561,10 @@
     void setEventThrottlingBehaviorOverride(std::optional<EventThrottlingBehavior> throttling) { m_eventThrottlingBehaviorOverride = throttling; }
 
     WebGLStateTracker* webGLStateTracker() const { return m_webGLStateTracker.get(); }
+
+    bool isOnlyNonUtilityPage() const;
+    bool isUtilityPage() const { return m_isUtilityPage; }
+
 private:
     WEBCORE_EXPORT void initGroup();
 
@@ -572,9 +578,6 @@
     void checkSubframeCountConsistency() const;
 #endif
 
-    void measurePostLoadCPUUsage();
-    void measurePostBackgroundingCPUUsage();
-
     enum ShouldHighlightMatches { DoNotHighlightMatches, HighlightMatches };
     enum ShouldMarkMatches { DoNotMarkMatches, MarkMatches };
 
@@ -756,15 +759,13 @@
     bool m_showAllPlugins { false };
     bool m_controlledByAutomation { false };
     bool m_resourceCachingDisabled { false };
+    bool m_isUtilityPage;
     UserInterfaceLayoutDirection m_userInterfaceLayoutDirection { UserInterfaceLayoutDirection::LTR };
     
     // For testing.
     std::optional<EventThrottlingBehavior> m_eventThrottlingBehaviorOverride;
 
-    Timer m_postPageLoadCPUUsageTimer;
-    std::optional<CPUTime> m_postLoadCPUTime;
-    Timer m_postBackgroundingCPUUsageTimer;
-    std::optional<CPUTime> m_postBackgroundingCPUTime;
+    std::unique_ptr<PerformanceMonitor> m_performanceMonitor;
 };
 
 inline PageGroup& Page::group()

Added: branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.cpp (0 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.cpp	                        (rev 0)
+++ branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PerformanceMonitor.h"
+
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "DiagnosticLoggingClient.h"
+#include "DiagnosticLoggingKeys.h"
+#include "Logging.h"
+#include "Page.h"
+#include "Settings.h"
+
+namespace WebCore {
+
+#define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(m_page.isAlwaysOnLoggingAllowed(), channel, "%p - PerformanceMonitor::" fmt, this, ##__VA_ARGS__)
+
+static const std::chrono::seconds cpuUsageMeasurementDelay { 5 };
+static const std::chrono::seconds postLoadCPUUsageMeasurementDuration { 10 };
+static const std::chrono::minutes backgroundCPUUsageMeasurementDuration { 5 };
+static const std::chrono::minutes cpuUsageSamplingInterval { 10 };
+
+static inline ActivityStateForCPUSampling activityStateForCPUSampling(ActivityState::Flags state)
+{
+    if (!(state & ActivityState::IsVisible))
+        return ActivityStateForCPUSampling::NonVisible;
+    if (state & ActivityState::WindowIsActive)
+        return ActivityStateForCPUSampling::VisibleAndActive;
+    return ActivityStateForCPUSampling::VisibleNonActive;
+}
+
+PerformanceMonitor::PerformanceMonitor(Page& page)
+    : m_page(page)
+    , m_postPageLoadCPUUsageTimer(*this, &PerformanceMonitor::measurePostLoadCPUUsage)
+    , m_postBackgroundingCPUUsageTimer(*this, &PerformanceMonitor::measurePostBackgroundingCPUUsage)
+    , m_perActivityStateCPUUsageTimer(*this, &PerformanceMonitor::measurePerActivityStateCPUUsage)
+{
+    ASSERT(!page.isUtilityPage());
+
+    if (Settings::isPerActivityStateCPUUsageMeasurementEnabled()) {
+        m_perActivityStateCPUTime = getCPUTime();
+        m_perActivityStateCPUUsageTimer.startRepeating(cpuUsageSamplingInterval);
+    }
+}
+
+void PerformanceMonitor::didStartProvisionalLoad()
+{
+    m_postLoadCPUTime = std::nullopt;
+    m_postPageLoadCPUUsageTimer.stop();
+}
+
+void PerformanceMonitor::didFinishLoad()
+{
+    // Only do post-load CPU usage measurement if there is a single Page in the process in order to reduce noise.
+    if (Settings::isPostLoadCPUUsageMeasurementEnabled() && m_page.isOnlyNonUtilityPage()) {
+        m_postLoadCPUTime = std::nullopt;
+        m_postPageLoadCPUUsageTimer.startOneShot(cpuUsageMeasurementDelay);
+    }
+}
+
+void PerformanceMonitor::activityStateChanged(ActivityState::Flags oldState, ActivityState::Flags newState)
+{
+    ActivityState::Flags changed = oldState ^ newState;
+    bool visibilityChanged = changed & ActivityState::IsVisible;
+
+    // Measure CPU usage of pages when they are no longer visible.
+    if (Settings::isPostBackgroundingCPUUsageMeasurementEnabled() && visibilityChanged) {
+        m_postBackgroundingCPUTime = std::nullopt;
+        if (newState & ActivityState::IsVisible)
+            m_postBackgroundingCPUUsageTimer.stop();
+        else if (m_page.isOnlyNonUtilityPage())
+            m_postBackgroundingCPUUsageTimer.startOneShot(cpuUsageMeasurementDelay);
+    }
+
+    if (Settings::isPerActivityStateCPUUsageMeasurementEnabled()) {
+        // If visibility changed then report CPU usage right away because CPU usage is connected to visibility state.
+        auto oldActivityStateForCPUSampling = activityStateForCPUSampling(oldState);
+        if (oldActivityStateForCPUSampling != activityStateForCPUSampling(newState)) {
+            measureCPUUsageInActivityState(oldActivityStateForCPUSampling);
+            m_perActivityStateCPUUsageTimer.startRepeating(cpuUsageSamplingInterval);
+        }
+    }
+}
+
+void PerformanceMonitor::measurePostLoadCPUUsage()
+{
+    if (!m_page.isOnlyNonUtilityPage()) {
+        m_postLoadCPUTime = std::nullopt;
+        return;
+    }
+
+    if (!m_postLoadCPUTime) {
+        m_postLoadCPUTime = getCPUTime();
+        if (m_postLoadCPUTime)
+            m_postPageLoadCPUUsageTimer.startOneShot(postLoadCPUUsageMeasurementDuration);
+        return;
+    }
+    std::optional<CPUTime> cpuTime = getCPUTime();
+    if (!cpuTime)
+        return;
+
+    double cpuUsage = cpuTime.value().percentageCPUUsageSince(*m_postLoadCPUTime);
+    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostLoadCPUUsage: Process was using %.1f%% CPU after the page load.", cpuUsage);
+    m_page.diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageLoadKey(), DiagnosticLoggingKeys::cpuUsageKey(), DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLoggingKey(cpuUsage), ShouldSample::No);
+}
+
+void PerformanceMonitor::measurePostBackgroundingCPUUsage()
+{
+    if (!m_page.isOnlyNonUtilityPage()) {
+        m_postBackgroundingCPUTime = std::nullopt;
+        return;
+    }
+
+    if (!m_postBackgroundingCPUTime) {
+        m_postBackgroundingCPUTime = getCPUTime();
+        if (m_postBackgroundingCPUTime)
+            m_postBackgroundingCPUUsageTimer.startOneShot(backgroundCPUUsageMeasurementDuration);
+        return;
+    }
+    std::optional<CPUTime> cpuTime = getCPUTime();
+    if (!cpuTime)
+        return;
+
+    double cpuUsage = cpuTime.value().percentageCPUUsageSince(*m_postBackgroundingCPUTime);
+    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measurePostBackgroundingCPUUsage: Process was using %.1f%% CPU after becoming non visible.", cpuUsage);
+    m_page.diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::postPageBackgroundingKey(), DiagnosticLoggingKeys::cpuUsageKey(), DiagnosticLoggingKeys::backgroundCPUUsageToDiagnosticLoggingKey(cpuUsage), ShouldSample::No);
+}
+
+void PerformanceMonitor::measurePerActivityStateCPUUsage()
+{
+    measureCPUUsageInActivityState(activityStateForCPUSampling(m_page.activityState()));
+}
+
+#if !RELEASE_LOG_DISABLED
+
+static inline const char* stringForCPUSamplingActivityState(ActivityStateForCPUSampling activityState)
+{
+    switch (activityState) {
+    case ActivityStateForCPUSampling::NonVisible:
+        return "NonVisible";
+    case ActivityStateForCPUSampling::VisibleNonActive:
+        return "VisibleNonActive";
+    case ActivityStateForCPUSampling::VisibleAndActive:
+        return "VisibleAndActive";
+    }
+}
+
+#endif
+
+void PerformanceMonitor::measureCPUUsageInActivityState(ActivityStateForCPUSampling activityState)
+{
+    if (!m_page.isOnlyNonUtilityPage()) {
+        m_perActivityStateCPUTime = std::nullopt;
+        return;
+    }
+
+    if (!m_perActivityStateCPUTime) {
+        m_perActivityStateCPUTime = getCPUTime();
+        return;
+    }
+
+    std::optional<CPUTime> cpuTime = getCPUTime();
+    if (!cpuTime) {
+        m_perActivityStateCPUTime = std::nullopt;
+        return;
+    }
+
+#if !RELEASE_LOG_DISABLED
+    double cpuUsage = cpuTime.value().percentageCPUUsageSince(*m_perActivityStateCPUTime);
+    RELEASE_LOG_IF_ALLOWED(PerformanceLogging, "measureCPUUsageInActivityState: Process is using %.1f%% CPU in state: %s", cpuUsage, stringForCPUSamplingActivityState(activityState));
+#endif
+    m_page.chrome().client().reportProcessCPUTime((cpuTime.value().systemTime + cpuTime.value().userTime) - (m_perActivityStateCPUTime.value().systemTime + m_perActivityStateCPUTime.value().userTime), activityState);
+
+    m_perActivityStateCPUTime = WTFMove(cpuTime);
+}
+
+} // namespace WebCore

Copied: branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.h (from rev 210963, branches/safari-603-branch/Source/WebCore/page/ActivityState.h) (0 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.h	                        (rev 0)
+++ branches/safari-603-branch/Source/WebCore/page/PerformanceMonitor.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ActivityState.h"
+#include "CPUTime.h"
+#include "Timer.h"
+#include <wtf/Optional.h>
+
+namespace WebCore {
+
+class Page;
+
+class PerformanceMonitor {
+public:
+    explicit PerformanceMonitor(Page&);
+
+    void didStartProvisionalLoad();
+    void didFinishLoad();
+    void activityStateChanged(ActivityState::Flags oldState, ActivityState::Flags newState);
+
+private:
+    void measurePostLoadCPUUsage();
+    void measurePostBackgroundingCPUUsage();
+    void measurePerActivityStateCPUUsage();
+    void measureCPUUsageInActivityState(ActivityStateForCPUSampling);
+
+    Page& m_page;
+
+    Timer m_postPageLoadCPUUsageTimer;
+    std::optional<CPUTime> m_postLoadCPUTime;
+    Timer m_postBackgroundingCPUUsageTimer;
+    std::optional<CPUTime> m_postBackgroundingCPUTime;
+    Timer m_perActivityStateCPUUsageTimer;
+    std::optional<CPUTime> m_perActivityStateCPUTime;
+};
+
+}

Modified: branches/safari-603-branch/Source/WebCore/page/Settings.cpp (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/Settings.cpp	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/Settings.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -778,24 +778,6 @@
 #endif
 }
 
-bool Settings::isPostLoadCPUUsageMeasurementEnabled()
-{
-#if PLATFORM(COCOA)
-    return true;
-#else
-    return false;
-#endif
-}
-
-bool Settings::isPostBackgroundingCPUUsageMeasurementEnabled()
-{
-#if PLATFORM(MAC)
-    return true;
-#else
-    return false;
-#endif
-}
-
 void Settings::setAllowsAnySSLCertificate(bool allowAnySSLCertificate)
 {
     gAllowsAnySSLCertificate = allowAnySSLCertificate;

Modified: branches/safari-603-branch/Source/WebCore/page/Settings.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebCore/page/Settings.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebCore/page/Settings.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -201,6 +201,7 @@
 
     static bool isPostLoadCPUUsageMeasurementEnabled();
     static bool isPostBackgroundingCPUUsageMeasurementEnabled();
+    static bool isPerActivityStateCPUUsageMeasurementEnabled();
 
     static bool globalConstRedeclarationShouldThrow();
 
@@ -423,4 +424,31 @@
     static bool gAllowsAnySSLCertificate;
 };
 
+inline bool Settings::isPostLoadCPUUsageMeasurementEnabled()
+{
+#if PLATFORM(COCOA)
+    return true;
+#else
+    return false;
+#endif
+}
+
+inline bool Settings::isPostBackgroundingCPUUsageMeasurementEnabled()
+{
+#if PLATFORM(MAC)
+    return true;
+#else
+    return false;
+#endif
+}
+
+inline bool Settings::isPerActivityStateCPUUsageMeasurementEnabled()
+{
+#if PLATFORM(MAC)
+    return true;
+#else
+    return false;
+#endif
+}
+
 } // namespace WebCore

Modified: branches/safari-603-branch/Source/WebKit2/ChangeLog (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/ChangeLog	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/ChangeLog	2017-01-20 16:56:17 UTC (rev 210964)
@@ -1,5 +1,39 @@
 2017-01-20  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210936. rdar://problem/30058349
+
+    2017-01-19  Chris Dumez  <cdu...@apple.com>
+
+            Implement per activity state CPU usage reporting using diagnostic logging
+            https://bugs.webkit.org/show_bug.cgi?id=167163
+            <rdar://problem/30058349>
+
+            Reviewed by Andreas Kling.
+
+            Implement per activity state CPU usage reporting using diagnostic logging.
+
+            * Platform/Logging.h:
+            * UIProcess/PerActivityStateCPUUsageSampler.cpp: Added.
+            (WebKit::PerActivityStateCPUUsageSampler::PerActivityStateCPUUsageSampler):
+            (WebKit::PerActivityStateCPUUsageSampler::~PerActivityStateCPUUsageSampler):
+            (WebKit::PerActivityStateCPUUsageSampler::reportWebContentCPUTime):
+            (WebKit::loggingKeyForActivityState):
+            (WebKit::loggingKeyForCPUUsage):
+            (WebKit::PerActivityStateCPUUsageSampler::loggingTimerFired):
+            (WebKit::PerActivityStateCPUUsageSampler::pageForLogging):
+            * UIProcess/PerActivityStateCPUUsageSampler.h: Copied from Source/WebCore/page/ActivityState.h.
+            * UIProcess/WebProcessPool.cpp:
+            (WebKit::WebProcessPool::WebProcessPool):
+            (WebKit::WebProcessPool::reportWebContentCPUTime):
+            * UIProcess/WebProcessPool.h:
+            * UIProcess/WebProcessPool.messages.in:
+            * WebKit2.xcodeproj/project.pbxproj:
+            * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+            (WebKit::WebChromeClient::reportProcessCPUTime):
+            * WebProcess/WebCoreSupport/WebChromeClient.h:
+
+2017-01-20  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r210913. rdar://problem/30086738
 
     2017-01-18  Said Abou-Hallawa  <sabouhall...@apple.com>

Modified: branches/safari-603-branch/Source/WebKit2/Platform/Logging.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/Platform/Logging.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/Platform/Logging.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -57,6 +57,7 @@
     M(NetworkCacheStorage) \
     M(NetworkScheduling) \
     M(NetworkSession) \
+    M(PerformanceLogging) \
     M(Plugins) \
     M(Printing) \
     M(ProcessSuspension) \

Added: branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.cpp (0 => 210964)


--- branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.cpp	                        (rev 0)
+++ branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PerActivityStateCPUUsageSampler.h"
+
+#include "Logging.h"
+#include "WebProcessPool.h"
+#include "WebProcessProxy.h"
+#include <WebCore/DiagnosticLoggingKeys.h>
+
+namespace WebKit {
+
+static const int64_t microsecondsPerSecond = 1000000;
+
+using namespace WebCore;
+
+static const std::chrono::minutes loggingInterval { 60 };
+
+PerActivityStateCPUUsageSampler::PerActivityStateCPUUsageSampler(WebProcessPool& processPool)
+    : m_processPool(processPool)
+    , m_loggingTimer(RunLoop::main(), this, &PerActivityStateCPUUsageSampler::loggingTimerFired)
+{
+    m_lastCPUTime = monotonicallyIncreasingTime();
+    m_loggingTimer.startRepeating(loggingInterval);
+}
+
+PerActivityStateCPUUsageSampler::~PerActivityStateCPUUsageSampler()
+{
+}
+
+void PerActivityStateCPUUsageSampler::reportWebContentCPUTime(int64_t cpuTime, ActivityStateForCPUSampling activityState)
+{
+    auto result = m_cpuTimeInActivityState.add(activityState, cpuTime);
+    if (!result.isNewEntry)
+        result.iterator->value += cpuTime;
+}
+
+static inline String loggingKeyForActivityState(ActivityStateForCPUSampling state)
+{
+    switch (state) {
+    case ActivityStateForCPUSampling::NonVisible:
+        return DiagnosticLoggingKeys::nonVisibleStateKey();
+    case ActivityStateForCPUSampling::VisibleNonActive:
+        return DiagnosticLoggingKeys::visibleNonActiveStateKey();
+    case ActivityStateForCPUSampling::VisibleAndActive:
+        return DiagnosticLoggingKeys::visibleAndActiveStateKey();
+    }
+}
+
+static inline String loggingKeyForCPUUsage(ActivityStateForCPUSampling state, double cpuUsage)
+{
+    switch (state) {
+    case ActivityStateForCPUSampling::NonVisible:
+        return DiagnosticLoggingKeys::backgroundCPUUsageToDiagnosticLoggingKey(cpuUsage);
+    case ActivityStateForCPUSampling::VisibleNonActive:
+    case ActivityStateForCPUSampling::VisibleAndActive:
+        return DiagnosticLoggingKeys::foregroundCPUUsageToDiagnosticLoggingKey(cpuUsage);
+    }
+}
+
+void PerActivityStateCPUUsageSampler::loggingTimerFired()
+{
+    auto* page = pageForLogging();
+    if (!page) {
+        m_cpuTimeInActivityState.clear();
+        return;
+    }
+
+    double currentCPUTime = monotonicallyIncreasingTime();
+    int64_t cpuTimeDelta = (currentCPUTime - m_lastCPUTime) * microsecondsPerSecond;
+
+    for (auto& pair : m_cpuTimeInActivityState) {
+        double cpuUsage = static_cast<double>(pair.value * 100.) / cpuTimeDelta;
+        String loggingKey = loggingKeyForActivityState(pair.key);
+        page->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::cpuUsageKey(), loggingKey, loggingKeyForCPUUsage(pair.key, cpuUsage), false);
+        RELEASE_LOG(PerformanceLogging, "WebContent processes used %.1f%% CPU in %s state", cpuUsage, loggingKey.utf8().data());
+    }
+
+    m_cpuTimeInActivityState.clear();
+    m_lastCPUTime = currentCPUTime;
+}
+
+WebPageProxy* PerActivityStateCPUUsageSampler::pageForLogging() const
+{
+    for (auto& webProcess : m_processPool.processes()) {
+        if (!webProcess->pageCount())
+            continue;
+        return *webProcess->pages().begin();
+    }
+    return nullptr;
+}
+
+} // namespace WebKit

Copied: branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.h (from rev 210963, branches/safari-603-branch/Source/WebCore/page/ActivityState.h) (0 => 210964)


--- branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.h	                        (rev 0)
+++ branches/safari-603-branch/Source/WebKit2/UIProcess/PerActivityStateCPUUsageSampler.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <WebCore/Page.h>
+#include <wtf/HashMap.h>
+#include <wtf/RunLoop.h>
+
+namespace WebKit {
+
+class WebPageProxy;
+class WebProcessPool;
+
+class PerActivityStateCPUUsageSampler {
+public:
+    explicit PerActivityStateCPUUsageSampler(WebProcessPool&);
+    ~PerActivityStateCPUUsageSampler();
+
+    void reportWebContentCPUTime(int64_t cpuTime, WebCore::ActivityStateForCPUSampling);
+
+private:
+    void loggingTimerFired();
+    WebPageProxy* pageForLogging() const;
+
+    WebProcessPool& m_processPool;
+    RunLoop::Timer<PerActivityStateCPUUsageSampler> m_loggingTimer;
+    typedef HashMap<WebCore::ActivityStateForCPUSampling, int64_t, WTF::IntHash<WebCore::ActivityStateForCPUSampling>, WTF::StrongEnumHashTraits<WebCore::ActivityStateForCPUSampling>> CPUTimeInActivityStateMap;
+    CPUTimeInActivityStateMap m_cpuTimeInActivityState;
+    double m_lastCPUTime;
+};
+
+} // namespace WebKit

Modified: branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.cpp (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.cpp	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -42,6 +42,7 @@
 #include "NetworkProcessCreationParameters.h"
 #include "NetworkProcessMessages.h"
 #include "NetworkProcessProxy.h"
+#include "PerActivityStateCPUUsageSampler.h"
 #include "SandboxExtension.h"
 #include "StatisticsData.h"
 #include "TextChecker.h"
@@ -168,6 +169,7 @@
     , m_websiteDataStore(m_configuration->shouldHaveLegacyDataStore() ? API::WebsiteDataStore::create(legacyWebsiteDataStoreConfiguration(m_configuration)).ptr() : nullptr)
 #if PLATFORM(MAC)
     , m_highPerformanceGraphicsUsageSampler(std::make_unique<HighPerformanceGraphicsUsageSampler>(*this))
+    , m_perActivityStateCPUUsageSampler(std::make_unique<PerActivityStateCPUUsageSampler>(*this))
 #endif
     , m_shouldUseTestingNetworkSession(false)
     , m_processTerminationEnabled(true)
@@ -1435,4 +1437,15 @@
     sendToAllProcesses(Messages::WebProcess::SetHiddenPageTimerThrottlingIncreaseLimit(limitInMilliseconds));
 }
 
+void WebProcessPool::reportWebContentCPUTime(int64_t cpuTime, uint64_t activityState)
+{
+#if PLATFORM(MAC)
+    if (m_perActivityStateCPUUsageSampler)
+        m_perActivityStateCPUUsageSampler->reportWebContentCPUTime(cpuTime, static_cast<WebCore::ActivityStateForCPUSampling>(activityState));
+#else
+    UNUSED_PARAM(cpuTime);
+    UNUSED_PARAM(activityState);
+#endif
+}
+
 } // namespace WebKit

Modified: branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -81,6 +81,7 @@
 class DownloadProxy;
 class HighPerformanceGraphicsUsageSampler;
 class UIGamepad;
+class PerActivityStateCPUUsageSampler;
 class WebAutomationSession;
 class WebContextSupplement;
 class WebIconDatabase;
@@ -254,6 +255,8 @@
     void clearCachedCredentials();
     void terminateDatabaseProcess();
 
+    void reportWebContentCPUTime(int64_t cpuTime, uint64_t activityState);
+
     void allowSpecificHTTPSCertificateForHost(const WebCertificateInfo*, const String& host);
 
     WebProcessProxy& createNewWebProcessRespectingProcessCountLimit(); // Will return an existing one if limit is met.
@@ -526,6 +529,7 @@
     RetainPtr<NSObject> m_automaticDashSubstitutionNotificationObserver;
 
     std::unique_ptr<HighPerformanceGraphicsUsageSampler> m_highPerformanceGraphicsUsageSampler;
+    std::unique_ptr<PerActivityStateCPUUsageSampler> m_perActivityStateCPUUsageSampler;
 #endif
 
     String m_overrideIconDatabasePath;

Modified: branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.messages.in (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.messages.in	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/UIProcess/WebProcessPool.messages.in	2017-01-20 16:56:17 UTC (rev 210964)
@@ -34,4 +34,6 @@
     # Plug-in messages.
     void AddPlugInAutoStartOriginHash(String pageOrigin, uint32_t hash, WebCore::SessionID sessionID)
     void PlugInDidReceiveUserInteraction(uint32_t hash, WebCore::SessionID sessionID)
+
+    ReportWebContentCPUTime(int64_t cpuTime, uint64_t activityState)
 }

Modified: branches/safari-603-branch/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj	2017-01-20 16:56:17 UTC (rev 210964)
@@ -1236,6 +1236,8 @@
 		831EEBBE1BD85C4300BB64C3 /* NetworkCacheSpeculativeLoad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 831EEBBC1BD85C4300BB64C3 /* NetworkCacheSpeculativeLoad.cpp */; };
 		832AE2521BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 832AE2501BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.h */; };
 		832AE2531BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 832AE2511BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.cpp */; };
+		832ED18B1E2FE157006BA64A /* PerActivityStateCPUUsageSampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 832ED1891E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.cpp */; };
+		832ED18C1E2FE157006BA64A /* PerActivityStateCPUUsageSampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 832ED18A1E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.h */; };
 		834B250F1A831A8D00CFB150 /* NetworkCacheFileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystem.h */; };
 		834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */; };
 		8360349F1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8360349D1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp */; };
@@ -3390,6 +3392,8 @@
 		831EEBBC1BD85C4300BB64C3 /* NetworkCacheSpeculativeLoad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheSpeculativeLoad.cpp; sourceTree = "<group>"; };
 		832AE2501BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheSpeculativeLoadManager.h; sourceTree = "<group>"; };
 		832AE2511BE2E8CD00FAAE10 /* NetworkCacheSpeculativeLoadManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheSpeculativeLoadManager.cpp; sourceTree = "<group>"; };
+		832ED1891E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PerActivityStateCPUUsageSampler.cpp; sourceTree = "<group>"; };
+		832ED18A1E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerActivityStateCPUUsageSampler.h; sourceTree = "<group>"; };
 		834B250E1A831A8D00CFB150 /* NetworkCacheFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheFileSystem.h; sourceTree = "<group>"; };
 		834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheStatistics.h; sourceTree = "<group>"; };
 		8360349D1ACB34D600626549 /* WebSQLiteDatabaseTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSQLiteDatabaseTracker.cpp; sourceTree = "<group>"; };
@@ -6274,6 +6278,8 @@
 				BC6EDAA5111271C600E7678B /* PageClient.h */,
 				1AC75379183A9FDA0072CB15 /* PageLoadState.cpp */,
 				1AC7537A183A9FDB0072CB15 /* PageLoadState.h */,
+				832ED1891E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.cpp */,
+				832ED18A1E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.h */,
 				37716A59195B910500EE8B1B /* ProcessAssertion.cpp */,
 				86F9536018FF4FD4001DB2EF /* ProcessAssertion.h */,
 				86E67A22190F411800004AB7 /* ProcessThrottler.cpp */,
@@ -8070,6 +8076,7 @@
 				CE1A0BD71A48E6C60054EF74 /* TextInputSPI.h in Headers */,
 				1AAF263914687C39004A1E8A /* TiledCoreAnimationDrawingArea.h in Headers */,
 				1AF05D8714688348008B1E81 /* TiledCoreAnimationDrawingAreaProxy.h in Headers */,
+				832ED18C1E2FE157006BA64A /* PerActivityStateCPUUsageSampler.h in Headers */,
 				1AFE436618B6C081009C7A48 /* UIDelegate.h in Headers */,
 				515BE1B51D5917FF00DD7C68 /* UIGamepad.h in Headers */,
 				515BE1A91D55293400DD7C68 /* UIGamepadProvider.h in Headers */,
@@ -9233,6 +9240,7 @@
 				93A88B471BC8829700ABA5C2 /* APIHitTestResult.cpp in Sources */,
 				7CD3A4821A5D02FA009623B8 /* APINavigation.cpp in Sources */,
 				BCF69FA31176D01400471A52 /* APINavigationData.cpp in Sources */,
+				832ED18B1E2FE157006BA64A /* PerActivityStateCPUUsageSampler.cpp in Sources */,
 				B63403F914910D57001070B5 /* APIObject.cpp in Sources */,
 				378E1A3D181ED6FF0031007A /* APIObject.mm in Sources */,
 				BC857FB612B830E600EDEB2E /* APIOpenPanelParameters.cpp in Sources */,

Modified: branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp	2017-01-20 16:56:17 UTC (rev 210964)
@@ -49,6 +49,7 @@
 #include "WebPageProxyMessages.h"
 #include "WebPopupMenu.h"
 #include "WebProcess.h"
+#include "WebProcessPoolMessages.h"
 #include "WebProcessProxyMessages.h"
 #include "WebSearchPopupMenu.h"
 #include <WebCore/ApplicationCacheStorage.h>
@@ -265,6 +266,11 @@
     m_page->runModal();
 }
 
+void WebChromeClient::reportProcessCPUTime(int64_t cpuTime, ActivityStateForCPUSampling activityState)
+{
+    WebProcess::singleton().send(Messages::WebProcessPool::ReportWebContentCPUTime(cpuTime, static_cast<uint64_t>(activityState)), 0);
+}
+
 void WebChromeClient::setToolbarsVisible(bool toolbarsAreVisible)
 {
     m_page->send(Messages::WebPageProxy::SetToolbarsAreVisible(toolbarsAreVisible));

Modified: branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h (210963 => 210964)


--- branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h	2017-01-20 16:25:55 UTC (rev 210963)
+++ branches/safari-603-branch/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h	2017-01-20 16:56:17 UTC (rev 210964)
@@ -74,6 +74,8 @@
     
     bool canRunModal() override;
     void runModal() override;
+
+    void reportProcessCPUTime(int64_t, WebCore::ActivityStateForCPUSampling) final;
     
     void setToolbarsVisible(bool) override;
     bool toolbarsVisible() override;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to