Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 1 | <!DOCTYPE html> |
| 2 | <!-- |
| 3 | Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 4 | Use of this source code is governed by a BSD-style license that can be |
| 5 | found in the LICENSE file. |
| 6 | --> |
| 7 | <link rel="import" href="/base/base.html"> |
| 8 | <link rel="import" href="/core/auditor.html"> |
Chris Craik | 1983215 | 2015-04-16 15:43:38 -0700 | [diff] [blame] | 9 | <link rel="import" href="/core/trace_model/event_info.html"> |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 10 | <link rel="import" href="/extras/audits/utils.html"> |
| 11 | <link rel="import" href="/extras/audits/chrome_model_helper.html"> |
Chris Craik | 44c2820 | 2015-05-12 17:25:16 -0700 | [diff] [blame^] | 12 | <link rel="import" href="/extras/audits/rail_ir_finder.html"> |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 13 | |
| 14 | <script> |
| 15 | 'use strict'; |
| 16 | |
| 17 | /** |
| 18 | * @fileoverview Base class for trace data Auditors. |
| 19 | */ |
| 20 | tv.exportTo('tv.e.audits', function() { |
| 21 | var Auditor = tv.c.Auditor; |
| 22 | |
| 23 | /** |
| 24 | * Auditor for Chrome-specific traces. |
| 25 | * @constructor |
| 26 | */ |
| 27 | function ChromeAuditor(model) { |
| 28 | this.model = model; |
| 29 | if (tv.e.audits.ChromeModelHelper.supportsModel(this.model)) { |
| 30 | var modelHelper = new tv.e.audits.ChromeModelHelper(this.model); |
| 31 | |
| 32 | // Must be a browser in order to do audits. |
| 33 | if (modelHelper.browser === undefined) |
| 34 | this.modelHelper = undefined; |
| 35 | else |
| 36 | this.modelHelper = modelHelper; |
| 37 | } else { |
| 38 | this.modelHelper = undefined; |
| 39 | } |
| 40 | }; |
| 41 | |
| 42 | ChromeAuditor.prototype = { |
| 43 | __proto__: Auditor.prototype, |
| 44 | |
Chris Craik | 1983215 | 2015-04-16 15:43:38 -0700 | [diff] [blame] | 45 | runAnnotate: function() { |
| 46 | if (!this.modelHelper) |
| 47 | return; |
| 48 | |
| 49 | this.model.getAllProcesses().forEach(function(process) { |
| 50 | if (process.labels !== undefined && |
| 51 | process.labels.length == 1 && |
| 52 | process.labels[0] == 'chrome://tracing') |
| 53 | process.important = false; |
| 54 | }); |
| 55 | }, |
| 56 | |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 57 | runAudit: function() { |
| 58 | if (!this.modelHelper) |
| 59 | return; |
| 60 | |
| 61 | // ChromeAuditor is disabled when used directly inside about://tracing, |
| 62 | // for now. |
| 63 | if (window.profilingView) |
| 64 | return; |
| 65 | |
| 66 | var allLoadAndNetEvents = this.getAllLoadAndNetEvents(); |
| 67 | var allFrameEvents = this.getAllFrameEvents(); |
| 68 | var allLatencyEvents = this.getAllLatencyEvents(); |
| 69 | var allFrameAndLatencyEvents = []; |
| 70 | allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents, |
| 71 | allFrameEvents); |
| 72 | allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents, |
| 73 | allLatencyEvents); |
| 74 | |
| 75 | function mergeEventsIntoIR(title, colorId, events) { |
| 76 | var e0 = events[0]; |
| 77 | var eN = events[events.length - 1]; |
| 78 | var ir = new tv.c.trace_model.InteractionRecord( |
| 79 | title, colorId, |
| 80 | e0.start, eN.end - e0.start); |
| 81 | ir.events = events; |
| 82 | return ir; |
| 83 | } |
| 84 | |
| 85 | var addIRs = function(records) { |
| 86 | records.forEach(function(ir) { |
| 87 | this.model.addInteractionRecord(ir); |
| 88 | }, this); |
| 89 | }.bind(this); |
| 90 | |
| 91 | var mergedLoadIRs = tv.e.audits.mergeEvents( |
| 92 | allLoadAndNetEvents, 300, |
| 93 | mergeEventsIntoIR.bind( |
| 94 | undefined, 'Loading/Net', |
| 95 | tv.b.ui.getColorIdForGeneralPurposeString('mt_loading'))); |
| 96 | addIRs(mergedLoadIRs); |
| 97 | |
| 98 | var mergedFrameIRs = tv.e.audits.mergeEvents( |
| 99 | allFrameEvents, 150, |
| 100 | mergeEventsIntoIR.bind( |
| 101 | undefined, 'Rendering', |
| 102 | tv.b.ui.getColorIdForGeneralPurposeString('mt_rendering'))); |
| 103 | addIRs(mergedFrameIRs); |
| 104 | |
Chris Craik | 44c2820 | 2015-05-12 17:25:16 -0700 | [diff] [blame^] | 105 | if (tv.e.audits.RAILIRFinder.supportsModelHelper(this.modelHelper)) { |
| 106 | var rirf = new tv.e.audits.RAILIRFinder(this.model, this.modelHelper); |
| 107 | var railIRs = rirf.findAllInteractionRecords(); |
| 108 | addIRs(railIRs); |
| 109 | } |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 110 | |
| 111 | this.addBigTaskAlerts(); |
| 112 | }, |
| 113 | |
| 114 | addBigTaskAlerts: function() { |
| 115 | var model = this.model; |
| 116 | tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) { |
| 117 | var slices = renderer.mainThread.sliceGroup.slices; |
| 118 | slices.forEach(function(slice) { |
| 119 | if (slice.category != 'toplevel') |
| 120 | return; |
| 121 | if (slice.duration > 75.0) { |
Chris Craik | 1983215 | 2015-04-16 15:43:38 -0700 | [diff] [blame] | 122 | var alertInfo = new tv.c.trace_model.EventInfo( |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 123 | 'Task too long', |
| 124 | 'Tasks taking >= 75ms are bad, and should be broken up to' + |
Chris Craik | 1983215 | 2015-04-16 15:43:38 -0700 | [diff] [blame] | 125 | 'ensure the main thread is responsive'); |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 126 | var center = slice.start + 0.5 * slice.duration; |
| 127 | var alert = new tv.c.trace_model.Alert( |
Chris Craik | 1983215 | 2015-04-16 15:43:38 -0700 | [diff] [blame] | 128 | alertInfo, center, [slice]); |
Chris Craik | b122baf | 2015-03-05 13:58:42 -0800 | [diff] [blame] | 129 | model.alerts.push(alert); |
| 130 | } |
| 131 | }); |
| 132 | }); |
| 133 | }, |
| 134 | |
| 135 | getAllLoadAndNetEvents: function() { |
| 136 | var model = this.model; |
| 137 | if (this.modelHelper.browser === undefined) |
| 138 | return; |
| 139 | var browser = this.modelHelper.browser; |
| 140 | |
| 141 | var events = []; |
| 142 | events.push.apply( |
| 143 | events, browser.getLoadingEventsInRange(model.bounds)); |
| 144 | events.push.apply( |
| 145 | events, browser.getAllNetworkEventsInRange(model.bounds)); |
| 146 | return events; |
| 147 | }, |
| 148 | |
| 149 | getAllFrameEvents: function() { |
| 150 | var model = this.model; |
| 151 | var frameEvents = []; |
| 152 | if (this.modelHelper.browser) { |
| 153 | var fe = this.modelHelper.browser.getFrameEventsInRange( |
| 154 | tv.e.audits.IMPL_FRAMETIME_TYPE, |
| 155 | model.bounds); |
| 156 | frameEvents.push.apply(frameEvents, fe); |
| 157 | } |
| 158 | tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) { |
| 159 | var fe = renderer.getFrameEventsInRange(tv.e.audits.IMPL_FRAMETIME_TYPE, |
| 160 | model.bounds); |
| 161 | frameEvents.push.apply(frameEvents, fe); |
| 162 | }, this); |
| 163 | frameEvents.sort(function(x, y) { return x.start - y.start; }); |
| 164 | return frameEvents; |
| 165 | }, |
| 166 | |
| 167 | getAllLatencyEvents: function() { |
| 168 | if (!this.modelHelper.browser) |
| 169 | return []; |
| 170 | return this.modelHelper.browser.getLatencyEventsInRange( |
| 171 | this.model.bounds); |
| 172 | } |
| 173 | }; |
| 174 | |
| 175 | Auditor.register(ChromeAuditor); |
| 176 | |
| 177 | return { |
| 178 | ChromeAuditor: ChromeAuditor |
| 179 | }; |
| 180 | }); |
| 181 | </script> |