blob: e2675b1f19ccbd7ddd99f7ff96c6ff7d71f8d184 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 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="/base/base.html">
<link rel="import" href="/core/auditor.html">
<link rel="import" href="/core/trace_model/event_info.html">
<link rel="import" href="/extras/audits/utils.html">
<link rel="import" href="/extras/audits/chrome_model_helper.html">
<link rel="import" href="/extras/audits/rail_ir_finder.html">
<script>
'use strict';
/**
* @fileoverview Base class for trace data Auditors.
*/
tv.exportTo('tv.e.audits', function() {
var Auditor = tv.c.Auditor;
/**
* Auditor for Chrome-specific traces.
* @constructor
*/
function ChromeAuditor(model) {
this.model = model;
if (tv.e.audits.ChromeModelHelper.supportsModel(this.model)) {
var modelHelper = new tv.e.audits.ChromeModelHelper(this.model);
// Must be a browser in order to do audits.
if (modelHelper.browser === undefined)
this.modelHelper = undefined;
else
this.modelHelper = modelHelper;
} else {
this.modelHelper = undefined;
}
};
ChromeAuditor.prototype = {
__proto__: Auditor.prototype,
runAnnotate: function() {
if (!this.modelHelper)
return;
this.model.getAllProcesses().forEach(function(process) {
if (process.labels !== undefined &&
process.labels.length == 1 &&
process.labels[0] == 'chrome://tracing')
process.important = false;
});
},
runAudit: function() {
if (!this.modelHelper)
return;
// ChromeAuditor is disabled when used directly inside about://tracing,
// for now.
if (window.profilingView)
return;
var allLoadAndNetEvents = this.getAllLoadAndNetEvents();
var allFrameEvents = this.getAllFrameEvents();
var allLatencyEvents = this.getAllLatencyEvents();
var allFrameAndLatencyEvents = [];
allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents,
allFrameEvents);
allFrameAndLatencyEvents.push.apply(allFrameAndLatencyEvents,
allLatencyEvents);
function mergeEventsIntoIR(title, colorId, events) {
var e0 = events[0];
var eN = events[events.length - 1];
var ir = new tv.c.trace_model.InteractionRecord(
title, colorId,
e0.start, eN.end - e0.start);
ir.events = events;
return ir;
}
var addIRs = function(records) {
records.forEach(function(ir) {
this.model.addInteractionRecord(ir);
}, this);
}.bind(this);
var mergedLoadIRs = tv.e.audits.mergeEvents(
allLoadAndNetEvents, 300,
mergeEventsIntoIR.bind(
undefined, 'Loading/Net',
tv.b.ui.getColorIdForGeneralPurposeString('mt_loading')));
addIRs(mergedLoadIRs);
var mergedFrameIRs = tv.e.audits.mergeEvents(
allFrameEvents, 150,
mergeEventsIntoIR.bind(
undefined, 'Rendering',
tv.b.ui.getColorIdForGeneralPurposeString('mt_rendering')));
addIRs(mergedFrameIRs);
if (tv.e.audits.RAILIRFinder.supportsModelHelper(this.modelHelper)) {
var rirf = new tv.e.audits.RAILIRFinder(this.model, this.modelHelper);
var railIRs = rirf.findAllInteractionRecords();
addIRs(railIRs);
}
this.addBigTaskAlerts();
},
addBigTaskAlerts: function() {
var model = this.model;
tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) {
var slices = renderer.mainThread.sliceGroup.slices;
slices.forEach(function(slice) {
if (slice.category != 'toplevel')
return;
if (slice.duration > 75.0) {
var alertInfo = new tv.c.trace_model.EventInfo(
'Task too long',
'Tasks taking >= 75ms are bad, and should be broken up to' +
'ensure the main thread is responsive');
var center = slice.start + 0.5 * slice.duration;
var alert = new tv.c.trace_model.Alert(
alertInfo, center, [slice]);
model.alerts.push(alert);
}
});
});
},
getAllLoadAndNetEvents: function() {
var model = this.model;
if (this.modelHelper.browser === undefined)
return;
var browser = this.modelHelper.browser;
var events = [];
events.push.apply(
events, browser.getLoadingEventsInRange(model.bounds));
events.push.apply(
events, browser.getAllNetworkEventsInRange(model.bounds));
return events;
},
getAllFrameEvents: function() {
var model = this.model;
var frameEvents = [];
if (this.modelHelper.browser) {
var fe = this.modelHelper.browser.getFrameEventsInRange(
tv.e.audits.IMPL_FRAMETIME_TYPE,
model.bounds);
frameEvents.push.apply(frameEvents, fe);
}
tv.b.iterItems(this.modelHelper.renderers, function(pid, renderer) {
var fe = renderer.getFrameEventsInRange(tv.e.audits.IMPL_FRAMETIME_TYPE,
model.bounds);
frameEvents.push.apply(frameEvents, fe);
}, this);
frameEvents.sort(function(x, y) { return x.start - y.start; });
return frameEvents;
},
getAllLatencyEvents: function() {
if (!this.modelHelper.browser)
return [];
return this.modelHelper.browser.getLatencyEventsInRange(
this.model.bounds);
}
};
Auditor.register(ChromeAuditor);
return {
ChromeAuditor: ChromeAuditor
};
});
</script>