Changeset 265163 in webkit
- Timestamp:
- Jul 31, 2020 3:23:52 PM (4 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r265162 r265163 1 2020-07-31 Chris Dumez <cdumez@apple.com> 2 3 Launch time regression due to EndowmentStateTracker initialization in WebPageProxy constructor 4 https://bugs.webkit.org/show_bug.cgi?id=215029 5 <rdar://problem/66362333> 6 7 Reviewed by Geoffrey Garen. 8 9 EndowmentStateTracker was expensive and in a critical code path during MobileSafari app launch. Since 10 this code is new, this was a net app launch time regression. To address the regression, the following 11 changes were made: 12 1. We only need the EndowmentStateTracker to monitor if the app is user-facing or not, so that we can 13 suspend / resume media playback as needed. As a result, it is unnecessary to start monitoring 14 user-facing state changes as soon as the WebPageProxy is constructed. Instead, we now wait until 15 media plays on the page for the first time. 16 2. It turns out that over 70% of CPU time in the EndowmentStateTracker constructor was spent getting 17 the current endownment for the process. As a result, I updated the code to lazy populate those 18 until they are requested for the first time. 19 3. The remaining 30% of CPU time in the EndowmentStateTracker constructor was spent constructing the 20 RBSProcessMonitor. I moved the initialization of the RBSProcessMonitor from the constructor to 21 EndowmentStateTracker::addClient() so that we only construct a monitor when we actually have our 22 first client. 23 4. All this code was actually only useful for Catalyst app and was therefore doing work on iOS for no 24 reason. I properly #ifdef'd out this code so that it now only applies to Catalyst apps. 25 26 * UIProcess/EndowmentStateTracker.h: 27 (WebKit::EndowmentStateTracker::isVisible const): 28 (WebKit::EndowmentStateTracker::isUserFacing const): 29 * UIProcess/EndowmentStateTracker.mm: 30 (WebKit::EndowmentStateTracker::stateFromEndowments): 31 (WebKit::EndowmentStateTracker::registerMonitorIfNecessary): 32 (WebKit::EndowmentStateTracker::addClient): 33 (WebKit::EndowmentStateTracker::ensureState const const): 34 (WebKit::EndowmentStateTracker::setState): 35 (WebKit::EndowmentStateTracker::EndowmentStateTracker): Deleted. 36 (WebKit::EndowmentStateTracker::setIsUserFacing): Deleted. 37 (WebKit::EndowmentStateTracker::setIsVisible): Deleted. 38 * UIProcess/WebPageProxy.cpp: 39 (WebKit::m_transcodingQueue): 40 (WebKit::WebPageProxy::updatePlayingMediaDidChange): 41 * UIProcess/WebPageProxy.h: 42 1 43 2020-07-31 Chris Dumez <cdumez@apple.com> 2 44 -
trunk/Source/WebKit/UIProcess/EndowmentStateTracker.h
r262858 r265163 31 31 #import <wtf/WeakHashSet.h> 32 32 33 OBJC_CLASS NSSet; 33 34 OBJC_CLASS RBSProcessMonitor; 34 35 … … 41 42 public: 42 43 static EndowmentStateTracker& singleton(); 43 ~EndowmentStateTracker();44 44 45 45 class Client : public CanMakeWeakPtr<Client> { … … 50 50 }; 51 51 52 bool isVisible() const { return m_isVisible; }53 bool isUserFacing() const { return m_isUserFacing; }52 bool isVisible() const { return ensureState().isVisible; } 53 bool isUserFacing() const { return ensureState().isUserFacing; } 54 54 55 55 void addClient(Client&); … … 60 60 private: 61 61 friend class NeverDestroyed<EndowmentStateTracker>; 62 EndowmentStateTracker(); 63 void setIsUserFacing(bool); 64 void setIsVisible(bool); 62 EndowmentStateTracker() = default; 63 64 void registerMonitorIfNecessary(); 65 66 struct State { 67 bool isUserFacing; 68 bool isVisible; 69 }; 70 static State stateFromEndowments(NSSet *endowments); 71 const State& ensureState() const; 72 void setState(State&&); 65 73 66 74 WeakHashSet<Client> m_clients; 67 75 RetainPtr<RBSProcessMonitor> m_processMonitor; 68 bool m_isUserFacing; 69 bool m_isVisible; 76 mutable Optional<State> m_state; 70 77 }; 71 78 -
trunk/Source/WebKit/UIProcess/EndowmentStateTracker.mm
r262866 r265163 73 73 } 74 74 75 inline auto EndowmentStateTracker::stateFromEndowments(NSSet *endowments) -> State 76 { 77 return State { 78 [endowments containsObject:userfacingEndowment], 79 [endowments containsObject:visibilityEndowment] 80 }; 81 } 82 75 83 bool EndowmentStateTracker::isApplicationForeground(pid_t pid) 76 84 { … … 84 92 } 85 93 86 EndowmentStateTracker::EndowmentStateTracker()94 void EndowmentStateTracker::registerMonitorIfNecessary() 87 95 { 88 auto processHandle = [RBSProcessHandle currentProcess];89 auto endowmentNamespaces = endowmentsForHandle(processHandle);96 if (m_processMonitor) 97 return; 90 98 91 m_isUserFacing = [endowmentNamespaces containsObject:userfacingEndowment]; 92 m_isVisible = [endowmentNamespaces containsObject:visibilityEndowment]; 93 94 m_processMonitor = [RBSProcessMonitor monitorWithConfiguration:[this, processHandle = retainPtr(processHandle)] (id<RBSProcessMonitorConfiguring> config) { 95 96 RBSProcessPredicate *processPredicate = [RBSProcessPredicate predicateMatchingHandle:processHandle.get()]; 99 m_processMonitor = [RBSProcessMonitor monitorWithConfiguration:[this] (id<RBSProcessMonitorConfiguring> config) { 100 [config setPredicates:@[[RBSProcessPredicate predicateMatchingHandle:[RBSProcessHandle currentProcess]]]]; 97 101 98 102 RBSProcessStateDescriptor *stateDescriptor = [RBSProcessStateDescriptor descriptor]; 99 103 stateDescriptor.endowmentNamespaces = @[visibilityEndowment, userfacingEndowment]; 100 101 [config setPredicates:@[processPredicate]];102 104 [config setStateDescriptor:stateDescriptor]; 103 105 104 106 [config setUpdateHandler:[this] (RBSProcessMonitor * _Nonnull monitor, RBSProcessHandle * _Nonnull process, RBSProcessStateUpdate * _Nonnull update) mutable { 105 dispatch_async(dispatch_get_main_queue(), [this, endowmentNamespaces = retainPtr(update.state.endowmentNamespaces)] { 106 setIsUserFacing([endowmentNamespaces containsObject:userfacingEndowment]); 107 setIsVisible([endowmentNamespaces containsObject:visibilityEndowment]); 107 dispatch_async(dispatch_get_main_queue(), [this, state = stateFromEndowments(update.state.endowmentNamespaces)]() mutable { 108 setState(WTFMove(state)); 108 109 }); 109 110 }]; … … 114 115 { 115 116 m_clients.add(client); 117 registerMonitorIfNecessary(); 116 118 } 117 119 … … 121 123 } 122 124 123 void EndowmentStateTracker::setIsUserFacing(bool isUserFacing) 125 auto EndowmentStateTracker::ensureState() const -> const State& 124 126 { 125 if (m_isUserFacing == isUserFacing) 127 if (!m_state) 128 m_state = stateFromEndowments(endowmentsForHandle([RBSProcessHandle currentProcess])); 129 return *m_state; 130 } 131 132 void EndowmentStateTracker::setState(State&& state) 133 { 134 bool isUserFacingChanged = !m_state || m_state->isUserFacing != state.isUserFacing; 135 bool isVisibleChanged = !m_state || m_state->isVisible != state.isVisible; 136 if (!isUserFacingChanged && !isVisibleChanged) 126 137 return; 127 m_isUserFacing = isUserFacing;128 138 129 RELEASE_LOG(ViewState, "%p - EndowmentStateTracker::setIsUserFacing(%{public}s)", this, isUserFacing ? "true" : "false"); 139 m_state = WTFMove(state); 140 141 RELEASE_LOG(ViewState, "%p - EndowmentStateTracker::setState() isUserFacing: %{public}s isVisible: %{public}s", this, m_state->isUserFacing ? "true" : "false", m_state->isVisible ? "true" : "false"); 130 142 131 143 for (auto& client : copyToVector(m_clients)) { 132 if (client) 133 client->isUserFacingChanged(m_isUserFacing); 134 } 135 } 136 137 void EndowmentStateTracker::setIsVisible(bool isVisible) 138 { 139 if (m_isVisible == isVisible) 140 return; 141 m_isVisible = isVisible; 142 143 RELEASE_LOG(ViewState, "%p - EndowmentStateTracker::setIsVisible(%{public}s)", this, isVisible ? "true" : "false"); 144 145 for (auto& client : copyToVector(m_clients)) { 146 if (client) 147 client->isVisibleChanged(m_isVisible); 144 if (isUserFacingChanged && client) 145 client->isUserFacingChanged(m_state->isUserFacing); 146 if (isVisibleChanged && client) 147 client->isVisibleChanged(m_state->isVisible); 148 148 } 149 149 } -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r265063 r265163 533 533 if (m_configuration->preferences()->serviceWorkerEntitlementDisabledForTesting()) 534 534 disableServiceWorkerEntitlementInNetworkProcess(); 535 536 EndowmentStateTracker::singleton().addClient(*this);537 535 #endif 538 536 … … 577 575 #endif 578 576 579 #if PLATFORM( IOS_FAMILY)577 #if PLATFORM(MACCATALYST) 580 578 EndowmentStateTracker::singleton().removeClient(*this); 581 579 #endif … … 8939 8937 return; 8940 8938 8939 #if PLATFORM(MACCATALYST) 8940 // When the page starts playing media for the first time, make sure we register with 8941 // the EndowmentStateTracker to get notifications when the application is no longer 8942 // user-facing, so that we can appropriately suspend all media playback. 8943 if (!m_isListeningForUserFacingStateChangeNotification) { 8944 EndowmentStateTracker::singleton().addClient(*this); 8945 m_isListeningForUserFacingStateChangeNotification = true; 8946 } 8947 #endif 8948 8941 8949 #if ENABLE(MEDIA_STREAM) 8942 8950 WebCore::MediaProducer::MediaStateFlags oldMediaCaptureState = m_mediaState & WebCore::MediaProducer::MediaCaptureMask; -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r264812 r265163 122 122 123 123 #if PLATFORM(IOS_FAMILY) 124 #include "EndowmentStateTracker.h"125 124 #include "GestureTypes.h" 126 125 #include "WebAutocorrectionContext.h" 126 #endif 127 128 #if PLATFORM(MACCATALYST) 129 #include "EndowmentStateTracker.h" 127 130 #endif 128 131 … … 435 438 , public WebCore::PlatformSpeechSynthesizerClient 436 439 #endif 437 #if PLATFORM( IOS_FAMILY)440 #if PLATFORM(MACCATALYST) 438 441 , public EndowmentStateTracker::Client 439 442 #else … … 1189 1192 void processWillBecomeSuspended(); 1190 1193 void processWillBecomeForeground(); 1194 #endif 1195 #if PLATFORM(MACCATALYST) 1191 1196 void isUserFacingChanged(bool) final; 1192 void isVisibleChanged(bool) final;1193 1197 #endif 1194 1198 … … 2473 2477 OptionSet<WebCore::ActivityState::Flag> m_activityState; 2474 2478 bool m_viewWasEverInWindow { false }; 2479 #if PLATFORM(MACCATALYST) 2480 bool m_isListeningForUserFacingStateChangeNotification { false }; 2481 #endif 2475 2482 #if PLATFORM(IOS_FAMILY) 2476 2483 bool m_allowsMediaDocumentInlinePlayback { false }; -
trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
r264907 r265163 1625 1625 } 1626 1626 1627 #if PLATFORM(MACCATALYST) 1627 1628 void WebPageProxy::isUserFacingChanged(bool isUserFacing) 1628 1629 { 1629 #if PLATFORM(MACCATALYST)1630 1630 if (!isUserFacing) 1631 1631 suspendAllMediaPlayback(); 1632 1632 else 1633 1633 resumeAllMediaPlayback(); 1634 #else 1635 UNUSED_PARAM(isUserFacing); 1634 } 1636 1635 #endif 1637 }1638 1639 void WebPageProxy::isVisibleChanged(bool isVisible)1640 {1641 UNUSED_PARAM(isVisible);1642 }1643 1636 1644 1637 #if PLATFORM(IOS)
Note: See TracChangeset
for help on using the changeset viewer.