| <!DOCTYPE html> |
| <!-- |
| Copyright 2015 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. |
| --> |
| |
| <link rel="import" href="/perf_insights/mre/function_handle.html"> |
| <link rel="import" href="/tracing/model/helpers/chrome_browser_helper.html"> |
| <link rel="import" href="/tracing/model/helpers/chrome_model_helper.html"> |
| |
| <script> |
| 'use strict'; |
| |
| tr.exportTo('pie', function() { |
| function eventCost(event) { |
| if (event.cpuDuration !== undefined) |
| return event.cpuDuration; |
| return event.duration; |
| } |
| |
| // Computes the thread time spent in BeginMainFrame during the loading phase |
| // as a ratio of the overall main thread utilization during that time. |
| // See https://goo.gl/l7V5xg. |
| function mapRenderingCost(result, model) { |
| var modelHelper = model.getOrCreateHelper( |
| tr.model.helpers.ChromeModelHelper); |
| var browserHelper = modelHelper.browserHelper; |
| var rendererHelpers = modelHelper.rendererHelpers; |
| |
| if (!browserHelper || !rendererHelpers) { |
| // If we couldn't find both a browser and a renderer process, bail out. |
| result.addPair('renderingCost', null); |
| return; |
| } |
| |
| var loadingEvents = browserHelper.getLoadingEventsInRange(model.bounds); |
| var loadingDurations = new Array(loadingEvents.length); |
| var loadingTotalCost = new Array(loadingEvents.length); |
| var loadingBeginMainFrameCost = new Array(loadingEvents.length); |
| var loadingBeginMainFrameRelativeCost = new Array(loadingEvents.length); |
| var beginMainFrameCount = 0; |
| loadingEvents.forEach(function(loadingEvent, index) { |
| loadingDurations[index] = loadingEvent.duration; |
| |
| var totalCost = 0; |
| var beginMainFrameCost = 0; |
| for (var pid in rendererHelpers) { |
| var rendererHelper = rendererHelpers[pid]; |
| var mainThread = rendererHelper.mainThread; |
| for (var event of mainThread.getDescendantEvents()) { |
| // Look for tasks executed by the scheduler. Note that this only |
| // includes slices that are *completely* inside the loading phase. |
| if (event.title !== 'TaskQueueManager::RunTask' || |
| event.start < loadingEvent.start || |
| event.start + event.duration > |
| loadingEvent.start + loadingEvent.duration) { |
| continue; |
| } |
| totalCost += eventCost(event); |
| |
| var beginMainFrame = |
| event.findDescendentSlice('ThreadProxy::BeginMainFrame'); |
| if (beginMainFrame) { |
| beginMainFrameCount++; |
| beginMainFrameCost += eventCost(beginMainFrame); |
| } |
| } |
| } |
| |
| loadingTotalCost[index] = totalCost; |
| loadingBeginMainFrameCost[index] = beginMainFrameCost; |
| loadingBeginMainFrameRelativeCost[index] = beginMainFrameCost / totalCost; |
| }); |
| |
| if (loadingDurations.length === 0) { |
| result.addValue('renderingCost', null); |
| return; |
| } |
| |
| result.addPair('renderingCost', { |
| loadingDuration: loadingDurations, |
| loadingTotalCost: loadingTotalCost, |
| loadingBeginMainFrameCost: loadingBeginMainFrameCost, |
| loadingBeginMainFrameRelativeCost: loadingBeginMainFrameRelativeCost, |
| beginMainFramesPerLoad: beginMainFrameCount / loadingDurations.length |
| }); |
| } |
| |
| pi.FunctionRegistry.register(mapRenderingCost); |
| |
| return { |
| mapRenderingCostForTest: mapRenderingCost |
| }; |
| }); |
| </script> |