| <!DOCTYPE html> |
| !-- |
| Copyright 2016 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('pi.m', function() { |
| var LONG_TASK_MS = 100; |
| |
| var UNINTERESTING_TASKS = [ |
| 'MessageLoop::RunTask', |
| 'TaskQueueManager::DoWork', |
| 'TaskQueueManager::ProcessTaskFromWorkQueue', |
| 'TaskQueueManager::RunTask', |
| 'TimerBase::run', |
| 'ThreadProxy::BeginMainFrame', |
| 'ParseHTML', |
| 'TimerFire', |
| 'EventDispatch', |
| 'WebViewImpl::updateAllLifecyclePhases', |
| 'ScheduledAction::execute', |
| 'HTMLDocumentParser::processParsedChunkFromBackgroundParser', |
| 'HTMLScriptRunner::executeScriptsWaitingForLoad', |
| 'ResourceDispatcher::OnRequestComplete', |
| 'HTMLScriptRunner::execute', |
| 'ChannelProxy::Context::OnDispatchMessage', |
| 'XHRReadyStateChange', |
| 'RenderFrameImpl::didFinishDocumentLoad', |
| 'ResourceDispatcher::OnReceivedData', |
| 'WebViewImpl::beginFrame', |
| 'RenderFrameImpl::OnBeforeUnload', |
| 'WindowProxy::initialize', |
| 'Sampler::InstallJitCodeEventHandler', |
| 'ResourceMsg_DataReceived', |
| 'ResourceReceivedData', |
| 'RenderWidgetInputHandler::OnHandleInputEvent', |
| 'ProxyMain::BeginMainFrame::commit', |
| 'ResourceMsg_RequestComplete', |
| 'ExtensionMsg_Response', |
| 'ExtensionMsg_MessageInvoke', |
| 'SyncChannel::Send', |
| 'SingleThreadIdleTaskRunner::RunTask', |
| 'ResourceDispatcher::OnReceivedResponse', |
| 'FireAnimationFrame', |
| 'InputMsg_HandleInputEvent', |
| 'WebURLLoaderImpl::Context::OnCompletedRequest', |
| 'WebURLLoaderImpl::Context::OnReceivedData', |
| 'v8.callFunction', |
| 'ExtensionMsg_Loaded', |
| 'ProxyMain::BeginMainFrame::commit', |
| 'XHRLoad', |
| 'RenderFrameImpl::OnNavigate', |
| 'CommitLoad', |
| 'FrameMsg_Navigate', |
| 'ResourceFinish', |
| 'RenderViewImpl::OnResize', |
| 'HostDispatcher::OnMessageReceived', |
| 'HTMLScriptRunner::executeScriptsWaitingForParsing', |
| 'HTMLScriptRunner::executeScriptsWaitingForResources', |
| 'FrameMsg_JavaScriptExecuteRequest', |
| 'v8.callModuleMethod' |
| ]; |
| |
| function longRunningScriptsMapper(result, model) { |
| var resultArray = []; |
| |
| iterateRendererMainThreads(model, function(thread) { |
| thread.sliceGroup.topLevelSlices.forEach(function(slice) { |
| |
| var interestingSlice = findLongestInterestingSlice(slice); |
| if (interestingSlice.duration < LONG_TASK_MS) |
| return; |
| |
| var scriptURL = getScriptURL(interestingSlice); |
| if (scriptURL !== undefined && scriptURL != '') { |
| var topLevelDomain = extractDomain(scriptURL); |
| resultArray.push({key: topLevelDomain, |
| float_value: interestingSlice.duration}); |
| } |
| }); |
| }); |
| |
| result.addPair('values', resultArray); |
| } |
| |
| |
| tr.mre.FunctionRegistry.register(longRunningScriptsMapper); |
| |
| return { |
| longRunningScriptsMapper: longRunningScriptsMapper |
| }; |
| |
| function iterateRendererMainThreads(model, cb, opt_this) { |
| var modelHelper = model.getOrCreateHelper( |
| tr.model.helpers.ChromeModelHelper); |
| tr.b.dictionaryValues(modelHelper.rendererHelpers).forEach( |
| function(rendererHelper) { |
| if (!rendererHelper.mainThread) |
| return; |
| cb.call(opt_this, rendererHelper.mainThread); |
| }); |
| } |
| |
| function getScriptURL(slice) { |
| var url = undefined; |
| |
| if (slice.title === 'v8.run') { |
| url = slice.args['fileName']; |
| } else if (slice.title === 'v8.compile') { |
| url = slice.args['fileName']; |
| } else if (slice.title === 'FunctionCall') { |
| url = slice.args['data']['scriptName']; |
| } else if (slice.title === 'EvaluateScript') { |
| url = slice.args['data']['url']; |
| } else if (slice.title === 'HTMLScriptRunner ExecuteScript') { |
| url = slice.args['data']['url']; |
| } |
| |
| return url; |
| } |
| |
| function findLongestInterestingSlice(slice) { |
| if (UNINTERESTING_TASKS.indexOf(slice.title) >= 0) { |
| var longestSlice = undefined; |
| var subSlices = slice.subSlices; |
| for (var i = 0; i < subSlices.length; ++i) { |
| if (longestSlice === undefined || |
| longestSlice.duration < subSlices[i].duration) { |
| longestSlice = subSlices[i]; |
| } |
| } |
| |
| if (longestSlice !== undefined) |
| return findLongestInterestingSlice(longestSlice); |
| } |
| |
| return slice; |
| } |
| |
| function extractDomain(url) { |
| var domain; |
| //find & remove protocol (http, ftp, etc.) and get domain |
| if (url.indexOf('://') > -1) { |
| domain = url.split('/')[2]; |
| } |
| else { |
| domain = url.split('/')[0]; |
| } |
| |
| //find & remove port number |
| domain = domain.split(':')[0]; |
| |
| return domain; |
| } |
| }); |
| |
| </script> |