通过腾讯bugly卡顿日志发现,有许多WebKit的卡顿信息,但是却没有定位到项目中的具体代码。通过大量观察发现很多日志中都有调用WebKit::WebPageProxy::processDidTerminate
函数或WebKit::WebMemoryPressureHandler::WebMemoryPressureHandler()
函数。参考WKWebView代理函数中的- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
函数成因及含有*Memory*
字段,因此大胆猜测可能是WKWebView内存占用过大,内存不足引起。
《WKWebView 那些坑》文章中WKWebView白屏问题小节介绍到在WKWebView上当总体的内存占用比较大的时候,webContent process会crash,从而出现白屏现象。此时系统会调用- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
函数,在该函数里执行[webView reload]
(这个时候webView.URL取值尚不为nil)解决白屏问题。
两者成因皆为WKWebView内存占用过大引起,故本次卡顿解决方式参考WKWebView白屏问题解决方法。
@property (nonatomic ,assign) BOOL webViewLoadTitle;//是否已获取当前webView的title
#pragma mark -
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (YES == self.webViewLoadTitle && [NSString isNullDataString:self.webView.title]) {
//webView已获取title,但返回时无法获取title,可能是内存不足原因造成,此时需重新加载同时避免第一次进入时重新加载
[self.webView reload];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (![NSString isNullDataString:self.webView.title]) {
self.webViewLoadTitle = YES;
}
}
#pragma mark - WKNavigationDelegate
//web内存过大,进程终止,重新加载webView
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
[webView reload];
}
结果:经生产版本检验,可有效防止WKWebView内存占用过大引起的卡顿问题。
- 参考文档:WKWebView那些坑
卡顿日志参考
0 WebKit WebKit::SandboxExtension::HandleArray::HandleArray()
1 WebKit WebKit::WebProcessCreationParameters::WebProcessCreationParameters() + 36
2 WebKit WebKit::WebProcessPool::initializeNewWebProcess(WebKit::WebProcessProxy&, WebKit::WebsiteDataStore&) + 156
3 WebKit WebKit::WebProcessPool::createNewWebProcess(WebKit::WebsiteDataStore&, WebKit::WebProcessProxy::IsInPrewarmedPool) + 60
4 WebKit WebKit::WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebKit::WebsiteDataStore&) + 232
5 WebKit WebKit::WebPageProxy::reattachToWebProcess() + 36
6 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 52
7 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 268
8 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 308
9 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 644
10 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 736
11 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 160
12 JavaScriptCore WTF::RunLoop::performWork() + 276
13 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
14 CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
0 libobjc.A.dylib class_createInstance + 36
1 libobjc.A.dylib _objc_rootAlloc + 52
2 libobjc.A.dylib _objc_rootAlloc + 52
3 UIKitCore +[UITextInteraction textInteractionsForSet:] + 36
4 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) addGestureRecognizersToView:] + 388
5 UIKitCore -[UIWKTextInteractionAssistant addGestureRecognizersToView:] + 68
6 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setGestureRecognizers] + 204
7 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) initWithView:textInteractionSet:] + 124
8 UIKitCore -[UIWKTextInteractionAssistant initWithView:] + 44
9 WebKit -[WKContentView(WKInteraction) setUpTextSelectionAssistant] + 92
10 WebKit -[WKContentView(WKInteraction) setupInteraction] + 1356
11 WebKit WebKit::PageClientImpl::didRelaunchProcess() + 36
12 WebKit WebKit::WebPageProxy::reattachToWebProcess(WTF::Ref >&&, API::Navigation*, WebKit::WebPageProxy::ReattachForBackForward) + 912
13 WebKit WebKit::WebPageProxy::reattachToWebProcess() + 80
14 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 52
15 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 268
16 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 308
17 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 644
18 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 736
19 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 160
20 JavaScriptCore WTF::RunLoop::performWork() + 276
21 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
22 CoreFoundation ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
0 WebKit 0x00000001c05f4000 + 4428800
1 WebKit WebKit::ViewSnapshotStore::singleton() + 52
2 WebKit _ZN3WTF8FunctionIFvNS_8CriticalENS_11SynchronousEEE15CallableWrapperIZN6WebKit28installMemoryPressureHandlerEvE3$_0E4callES1_S2_ + 24
3 JavaScriptCore WTF::MemoryPressureHandler::releaseMemory(WTF::Critical, WTF::Synchronous) + 92
4 JavaScriptCore ___ZN3WTF21MemoryPressureHandler7installEv_block_invoke_2 + 140
0 libsystem_kernel.dylib kevent_id + 8
1 libdispatch.dylib __dispatch_kq_poll + 332
2 libdispatch.dylib __dispatch_event_loop_wait_for_ownership$VARIANT$mp + 412
3 libdispatch.dylib ___DISPATCH_WAIT_FOR_QUEUE__ + 296
4 libdispatch.dylib __dispatch_sync_f_slow + 140
5 AssertionServices -[BKSAssertion setInvalidationHandler:] + 144
6 WebKit WebKit::ProcessAssertion::ProcessAssertion(int, WebKit::AssertionState, WTF::Function&&) + 472
7 WebKit WebKit::ProcessAndUIAssertion::ProcessAndUIAssertion(int, WebKit::AssertionState) + 96
8 WebKit WebKit::ProcessThrottler::didConnectToProcess(int) + 224
9 WebKit WebKit::WebProcessProxy::didFinishLaunching(WebKit::ProcessLauncher*, IPC::Connection::Identifier) + 576
10 WebKit WebKit::ProcessLauncher::didFinishLaunchingProcess(int, IPC::Connection::Identifier) + 124
11 WebKit ___ZN6WebKit15ProcessLauncher13launchProcessEv_block_invoke + 136
12 libxpc.dylib __xpc_connection_reply_callout + 60
0 WebKit -[WKContentView(WKInteraction) isEditable]
1 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) addGestureRecognizersToView:] + 120
2 UIKitCore -[UIWKTextInteractionAssistant addGestureRecognizersToView:] + 68
3 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) setGestureRecognizers] + 200
4 UIKitCore -[UITextInteractionAssistant(UITextInteractionAssistant_Internal) initWithView:textInteractionSet:] + 124
5 UIKitCore -[UIWKTextInteractionAssistant initWithView:] + 44
6 WebKit -[WKContentView(WKInteraction) setUpTextSelectionAssistant] + 92
7 WebKit -[WKContentView(WKInteraction) setupInteraction] + 1636
8 WebKit WebKit::PageClientImpl::didRelaunchProcess() + 36
9 WebKit WebKit::WebPageProxy::finishAttachingToWebProcess(WebKit::WebPageProxy::ShouldInitializeWebPage) + 460
10 WebKit WebKit::WebPageProxy::reattachToWebProcess() + 388
11 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 348
12 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 436
13 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 272
14 WebKit WebKit::WebPageProxy::dispatchProcessDidTerminate(WebKit::ProcessTerminationReason) + 268
15 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 684
16 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 916
17 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 140
18 JavaScriptCore WTF::RunLoop::performWork() + 340
19 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
20 CoreFoundation 0x000000023a172000 + 700188
0 WebKit API::Navigation::Navigation(WebKit::WebNavigationState&)
1 WebKit WebKit::WebNavigationState::createReloadNavigation() + 44
2 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 372
3 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 436
4 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 272
5 WebKit WebKit::WebPageProxy::dispatchProcessDidTerminate(WebKit::ProcessTerminationReason) + 268
6 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 684
7 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 916
8 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 140
9 JavaScriptCore WTF::RunLoop::performWork() + 276
10 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
0 WebKit WTF::Mapper WTF::copyToVectorOf > >(WTF::HashSet > const&)::'lambda'(WTF::String const&), WTF::HashSet > const&, void>::map(WTF::HashSet > const&, WTF::Vector WTF::copyToVectorOf > >(WTF::HashSet > const&)::'lambda'(WTF::String const&) const&)
1 WebKit WebKit::WebProcessPool::initializeNewWebProcess(WebKit::WebProcessProxy&, WebKit::WebsiteDataStore&) + 836
2 WebKit WebKit::WebProcessPool::createNewWebProcess(WebKit::WebsiteDataStore&, WebKit::WebProcessProxy::IsPrewarmed) + 84
3 WebKit WebKit::WebProcessPool::createNewWebProcessRespectingProcessCountLimit(WebKit::WebsiteDataStore&) + 228
4 WebKit WebKit::WebPageProxy::reattachToWebProcess() + 252
5 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 348
6 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 436
7 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 272
8 WebKit WebKit::WebPageProxy::dispatchProcessDidTerminate(WebKit::ProcessTerminationReason) + 268
9 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 684
10 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 916
11 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 140
12 JavaScriptCore WTF::RunLoop::performWork() + 340
13 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
0 WebKit WebKit::ViewSnapshotStore::singleton()
1 WebKit invocation function for block in WebKit::WebMemoryPressureHandler::WebMemoryPressureHandler() + 12
2 libdispatch.dylib __dispatch_client_callout + 16
0 WebKit WebKit::SecItemShimProxy::singleton()
1 WebKit WebKit::WebProcessProxy::connectionWillOpen(IPC::Connection&) + 48
2 WebKit WebKit::ChildProcessProxy::didFinishLaunching(WebKit::ProcessLauncher*, IPC::Connection::Identifier) + 196
3 WebKit WebKit::WebProcessProxy::didFinishLaunching(WebKit::ProcessLauncher*, IPC::Connection::Identifier) + 96
4 WebKit WebKit::ProcessLauncher::didFinishLaunchingProcess(int, IPC::Connection::Identifier) + 124
5 WebKit ___ZN6WebKit15ProcessLauncher13launchProcessEv_block_invoke + 136
6 libxpc.dylib __xpc_connection_reply_callout + 60
0 WebCore WebCore::HTTPHeaderMap::HTTPHeaderMap() + 0
1 WebKit WebCore::ResourceRequestBase::ResourceRequestBase(WTF::URL const&, WebCore::ResourceRequestCachePolicy) + 152
2 WebKit WebCore::ResourceRequest::ResourceRequest() + 48
3 WebKit API::Navigation::Navigation(WebKit::WebNavigationState&) + 64
4 WebKit WebKit::WebNavigationState::createReloadNavigation() + 44
5 WebKit WebKit::WebPageProxy::reattachToWebProcessForReload() + 372
6 WebKit WebKit::WebPageProxy::reload(WTF::OptionSet) + 436
7 WebKit WebKit::WebPageProxy::tryReloadAfterProcessTermination() + 272
8 WebKit WebKit::WebPageProxy::dispatchProcessDidTerminate(WebKit::ProcessTerminationReason) + 268
9 WebKit WebKit::WebPageProxy::processDidTerminate(WebKit::ProcessTerminationReason) + 684
10 WebKit WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch() + 916
11 WebKit WebKit::WebProcessProxy::didClose(IPC::Connection&) + 140
12 JavaScriptCore WTF::RunLoop::performWork() + 340
13 JavaScriptCore WTF::RunLoop::performWork(void*) + 36
14 CoreFoundation 0x00000001a728a000 + 700188