blob: fe01a39dade8cc19a387c44098778a80cafde0b3 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 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/mappers/slice_cost.html">
<link rel="import" href="/perf_insights/ui/caching_column.html">
<link rel="import" href="/perf_insights/ui/reports/pi_report.html">
<link rel="import" href="/tracing/ui/base/dom_helpers.html">
<link rel="import" href="/tracing/ui/base/grouping_table.html">
<link rel="import" href="/tracing/ui/base/info_bar_group.html">
<link rel="import" href="/tracing/ui/base/overlay.html">
<link rel="import" href="/tracing/ui/base/table.html">
<link rel="import" href="/tracing/value/ui/histogram_span.html">
<link rel="import" href="/tracing/value/ui/scalar_span.html">
<link rel="import" href="/tracing/value/unit.html">
<polymer-element name="pi-ui-r-startup-report"
extends="pi-ui-r-pi-report"
map-function-href="/perf_insights/mappers/startup_map_function.html"
map-function-name="startupMapFunction"
<template>
<style>
:host {
display: flex;
flex-direction: column;
}
top-controls {
display: flex;
flex: 0 0 auto;
flex-flow: wrap;
background-color: rgb(236, 236, 236);
border-bottom: 1px solid #8e8e8e;
padding: 4px;
}
content-pane {
min-height: 0;
display: flex;
flex-direction: row;
}
table-container {
flex: 1 1 60%;
display: flex;
overflow: auto;
}
#tableLeft {
flex: 1 1 60%;
}
#tableRight {
flex: 1 1 60%;
}
pane {
border-left: 1px solid black;
display: flex;
flex-direction: column;
flex: 1 1 40%;
}
#links {
min-height: 0;
overflow: auto;
}
</style>
<top-controls>
Slow trace threshold :&nbsp<input id="threshold"></input>ms
</top-controls>
<content-pane>
<pane>
<div>Fast startup traces (<span id="numFast"></span> traces)</div>
<table-container>
<tr-ui-b-grouping-table id="tableFast"></tr-ui-b-grouping-table>
</table-container>
</pane>
<pane>
<div>Slow startup traces (<span id="numSlow"></span> traces)</div>
<table-container>
<tr-ui-b-grouping-table id="tableSlow"></tr-ui-b-grouping-table>
</table-container>
</pane>
</content-pane>
</template>
</polymer-element>
<script>
'use strict';
(function() {
var DEFAULT_SLOW_THRESHOLD_MS = 3500;
Polymer('pi-ui-r-startup-report', {
created: function() {
this.mapResults_ = undefined;
this.slowThresholdMs_ = DEFAULT_SLOW_THRESHOLD_MS;
this.copyingState_ = false; // True when copying state between tables.
},
ready: function() {
this.$.threshold.value = DEFAULT_SLOW_THRESHOLD_MS;
this.$.tableFast.addEventListener('selection-changed',
this.copySelectedRow_.bind(this, this.$.tableFast, this.$.tableSlow));
this.$.tableSlow.addEventListener('selection-changed',
this.copySelectedRow_.bind(this, this.$.tableSlow, this.$.tableFast));
this.$.tableFast.addEventListener('sort-column-changed',
this.copySortingState_.bind(this, this.$.tableSlow));
this.$.tableSlow.addEventListener('sort-column-changed',
this.copySortingState_.bind(this, this.$.tableFast));
this.$.threshold.addEventListener(
'change', this.onThresholdChanged_.bind(this));
},
get mapResults() {
return this.mapResults_;
},
set mapResults(mapResults) {
this.mapResults_ = mapResults;
this.updateContents_();
},
// Looks at the selected row in |fromTable| and select the matching one in
// |toTable|.
copySelectedRow_: function(fromTable, toTable) {
// Block reentrant calls.
if (this.copyingState_)
return;
this.copyingState_ = true;
var rowToSelect = undefined;
var selectedRow = fromTable.selectedTableRow;
if (selectedRow !== undefined) {
toTable.tableRows.forEach(function(row) {
if (row.title === selectedRow.title)
rowToSelect = row;
});
}
toTable.selectedTableRow = rowToSelect;
this.copyingState_ = false;
},
// Apply the sorting state of |fromTable| to |toTable|.
copySortingState_: function(toTable, event) {
// Block reentrant calls.
if (this.copyingState_)
return;
this.copyingState_ = true;
if (toTable.tableColumns.length >= event.sortColumnIndex) {
toTable.sortColumnIndex = event.sortColumnIndex;
toTable.sortDescending = event.sortDescending;
}
this.copyingState_ = false;
},
onThresholdChanged_: function(event) {
var value = parseInt(this.$.threshold.value);
if (!Number.isInteger(value))
value = DEFAULT_SLOW_THRESHOLD_MS;
this.$.threshold.value = value;
this.slowThresholdMs_ = value;
this.updateContents_();
},
updateContents_: function() {
this.updateTable_(this.$.tableFast, this.$.numFast, function(value) {
return value.startupDuration < this.slowThresholdMs_;
}.bind(this));
this.updateTable_(this.$.tableSlow, this.$.numSlow, function(value) {
return value.startupDuration >= this.slowThresholdMs_;
}.bind(this));
},
updateTable_: function(table, numTracesSpan, filter) {
var results = this.mapResults_;
if (!results)
results = [];
var allSliceCosts = [];
var numTraces = 0;
var totalStartupDuration = 0;
results.forEach(function(result) {
var sr = result.pairs.sr;
if (sr === undefined)
return;
numTraces++;
totalStartupDuration += sr.startupDuration;
sr.sliceCosts.forEach(function(item) {
var sliceCostInfo = pi.m.SliceCostInfo.fromDict(item);
allSliceCosts.push({
canonicalUrl: result.pairs.canonical_url,
sliceCostInfo: sliceCostInfo
});
});
});
numTracesSpan.innerText = numTraces;
var columns = this.createColumns_(totalStartupDuration);
table.tableColumns = columns;
table.sortColumnIndex = 2;
table.sortDescending = true;
var groupBy = [];
groupBy.push(function(datum) {
return datum.sliceCostInfo.title;
});
table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
table.groupBy = groupBy;
table.dataToGroup = allSliceCosts;
table.rebuild();
},
createColumns_: function(totalStartupDuration) {
var columns = [
{
title: 'Title',
value: function(row) {
return row.title;
},
cmp: function(a, b) {
return a.title.localeCompare(b.title);
},
width: '500px'
},
this.createCachingColumn_('Relative self time', totalStartupDuration,
function(datum) {
return datum.sliceCostInfo.selfTime;
}),
this.createCachingColumn_('Relative CPU time', totalStartupDuration,
function(datum) {
return datum.sliceCostInfo.cpuSelfTime;
})
];
return columns;
},
createCachingColumn_(title, totalStartupDuration, getDataFunction) {
function computeStats(sliceCostInfo) {
var mean = tr.b.Statistics.sum(sliceCostInfo, getDataFunction);
if (mean == undefined || totalStartupDuration == 0)
return undefined;
mean /= totalStartupDuration;
var span = tr.ui.units.createScalarSpan(mean);
span.unit = tr.v.Unit.byName.normalizedPercentage;
span.percentage = mean;
return span;
}
var column = new pi.ui.CachingColumn(title, computeStats);
column.textAlign = 'right';
column.cmp = function(row0, row1) {
var value0 = column.value(row0);
var value1 = column.value(row1);
return tr.b.comparePossiblyUndefinedValues(value0, value1,
function(v0, v1) {
return v0.value - v1.value;
});
};
return column;
}
});
})();
</script>