blob: bfd796c97371937c5b37933bfca1eef5f2160678 [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="/tracing/ui/base/dom_helpers.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/ui/units/time_duration_span.html">
<link rel="import" href="/tracing/ui/units/histogram_span.html">
<link rel="import" href="/perf_insights/results/results.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="/perf_insights/ui/grouping_table.html">
<link rel="import" href="/perf_insights/ui/generic_results_view.html">
<link rel="import" href="/perf_insights/ui/trace_link_list.html">
<link rel="import" href="/perf_insights/mappers/slice_cost.html">
<polymer-element name="pi-ui-r-slice-cost-report"
extends="pi-ui-r-pi-report"
map-function-href="/perf_insights/mappers/weather_report_map_function.html"
map-function-name="weatherReportMapFunction">
<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;
}
#table {
flex: 1 1 60%;
}
right-pane {
border-left: 1px solid black;
display: flex;
flex-direction: column;
flex: 1 1 40%;
}
right-pane > * {
margin-bottom: 20px;
}
#links {
min-height: 0;
overflow: auto;
}
</style>
<top-controls></top-controls>
<content-pane>
<table-container>
<pi-ui-grouping-table id="table"></pi-ui-grouping-table>
</table-container>
<right-pane>
<div id="script-costs">
Script costs
<tr-ui-b-table id="script-costs-table"></tr-ui-b-table>
</div>
<div id="costs-histogram-container">
Histogram of
<select id="costs-histogram-cost-type"></select> values:
<tr-ui-u-histogram-span id="costs-histogram"></tr-ui-u-histogram-span>
Links
<pi-ui-trace-link-list id="links"></pi-ui-trace-link-list>
</div>
</div>
</content-pane>
</template>
<script>
'use strict';
Polymer({
created: function() {
this.mapResults_ = undefined;
},
ready: function() {
this.$.table.addEventListener(
'selection-changed', this.onSelectionChanged_.bind(this));
var topControls = this.shadowRoot.querySelector('top-controls');
this.groupByThreadName_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByThreadName', true,
'Group by thread name',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByThreadName_);
this.groupByRAILTypeName_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByRAILTypeName', true,
'Group by RAIL Stage',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByRAILTypeName_);
this.groupByUserFriendlyCategory_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByUserFriendlyCategory', true,
'Group by Event Category',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByUserFriendlyCategory_);
this.groupByTitle_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByTitle', false,
'Group by Event Title',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByTitle_);
this.groupByDomainCategory_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByDomainCategory', true,
'Group by Domain Category',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByDomainCategory_);
this.groupByDomain_ = tr.ui.b.createCheckBox(
undefined, undefined,
'pi.ui.wr.weather_report.groupByDomain', true,
'Group by Domain',
this.updateContents_.bind(this));
topControls.appendChild(this.groupByDomain_);
this.updateRightPane_();
this.initCostsHistogram_();
},
get mapResults() {
return this.mapResults_;
},
set mapResults(mapResults) {
this.mapResults_ = mapResults;
this.updateContents_();
},
onSelectionChanged_: function(event) {
this.updateRightPane_();
},
updateRightPane_: function() {
this.updateScriptCosts_();
this.updateCostsHistogram_();
var panes = this.shadowRoot.querySelector('right-pane').children;
var isFirst = true;
for (var i = 0; i < panes.length; i++) {
if (getComputedStyle(panes[i]).display === 'none')
continue;
if (isFirst) {
panes[i].style.borderTop = '';
isFirst = false;
continue;
}
panes[i].style.borderTop = '1px solid black';
}
},
updateScriptCosts_: function() {
var rows = [];
var footerRows = [];
// Aggregate values.
var aggregated = new pi.m.SliceCostInfo();
if (this.$.table.selectedTableRow) {
this.$.table.selectedTableRow.data.forEach(function(datum) {
aggregated.push(undefined, datum.sliceCostInfo);
});
}
if (aggregated.jsTime === 0) {
this.shadowRoot.querySelector('#script-costs').style.display = 'none';
return;
}
this.shadowRoot.querySelector('#script-costs').style.display = '';
// Display aggregated data.
for (var state in tr.model.source_info.JSSourceState) {
var stateName = tr.model.source_info.JSSourceState[state];
rows.push({
label: stateName,
value: tr.ui.units.createTimeDurationSpan(
aggregated.jsTimeByState[stateName])
});
}
footerRows.push({
label: 'JS Time',
value: tr.ui.units.createTimeDurationSpan(aggregated.jsTime)
});
// Push to table.
var scriptCostsTable = this.shadowRoot.querySelector(
'#script-costs-table');
scriptCostsTable.tableColumns = [
{
title: 'Label',
value: function(row) { return row.label; },
width: '150px'
},
{
title: 'Value',
value: function(row) { return row.value; },
width: '100%'
}
];
scriptCostsTable.showHeader = false;
scriptCostsTable.tableRows = rows;
scriptCostsTable.footerRows = footerRows;
scriptCostsTable.rebuild();
},
updateContents_: function() {
var table = this.$.table;
var results = this.mapResults_;
if (!results)
results = new tr.r.Results();
var columns = this.createColumns_();
table.tableColumns = columns;
table.sortColumnIndex = 2;
table.sortDescending = true;
var allSliceCosts = [];
results.allValuesFromFailureFreeRuns.forEach(function(result) {
if (result.name != 'wr')
return;
result.value.sliceCosts.forEach(function(item) {
var sliceCostInfo = pi.m.SliceCostInfo.fromDict(item);
allSliceCosts.push({
runInfo: result.runInfo,
sliceCostInfo: sliceCostInfo
});
});
});
var groupBy = [];
if (this.groupByThreadName_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.threadGroup;
});
}
if (this.groupByRAILTypeName_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.railTypeName;
});
}
if (this.groupByUserFriendlyCategory_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.userFriendlyCategory || 'other';
});
}
var didGroupByDomainCategoryOrDomain;
if (groupBy.length === 0) {
if (this.groupByDomainCategory_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.domainCategory;
});
didGroupByDomainCategoryOrDomain = true;
}
if (this.groupByDomain_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.domain;
});
didGroupByDomainCategoryOrDomain = true;
}
}
if (this.groupByTitle_.checked) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.title;
});
}
if (this.groupByDomainCategory_.checked &&
!didGroupByDomainCategoryOrDomain) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.domainCategory;
});
}
if (this.groupByDomain_.checked && !didGroupByDomainCategoryOrDomain) {
groupBy.push(function(datum) {
return datum.sliceCostInfo.domain;
});
}
table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
table.groupBy = groupBy;
table.dataToGroup = allSliceCosts;
table.rebuild();
this.updateRightPane_();
},
createColumns_: function() {
var columns = [
{
title: 'Title',
value: function(row) {
return row.title;
},
cmp: function(a, b) {
return a.title.localeCompare(b.title);
},
width: '500px'
},
this.createCachingColumn_('Self time (total)', function(datum) {
return datum.sliceCostInfo.selfTime;
}),
this.createCachingColumn_('CPU Self time (total)', function(datum) {
return datum.sliceCostInfo.cpuSelfTime;
})
];
return columns;
},
createCachingColumn_(title, getDataFunction) {
function computeStats(sliceCostInfo) {
var sum = tr.b.Statistics.sum(sliceCostInfo, getDataFunction);
return sum === undefined ? undefined :
tr.ui.units.createTimeDurationSpan(sum);
}
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.duration - v1.duration;
});
};
return column;
},
initCostsHistogram_: function() {
var histogram = this.shadowRoot.querySelector('#costs-histogram');
histogram.addEventListener('brushed-bins-changed',
this.onBrushedBinsChanged_.bind(this));
var options = [
{
label: 'Self time',
value: 'selfTime',
func: function(datum) { return datum.sliceCostInfo.selfTime; }
},
{
label: 'CPU self time',
value: 'cpuSelfTime',
func: function(datum) { return datum.sliceCostInfo.cpuSelfTime; }
},
{
label: 'JS time',
value: 'jsTime',
func: function(datum) { return datum.sliceCostInfo.jsTime; }
}
];
for (var state in tr.model.source_info.JSSourceState) {
options.push({
label: 'JS time: ' + state,
value: 'jsTime.' + state,
func: function(datum) {
return datum.sliceCostInfo.jsTimeByState[state];
}
});
}
var oldSelector = this.shadowRoot.querySelector(
'#costs-histogram-cost-type');
var newSelector = tr.ui.b.createSelector(
this, 'currentSliceReportCostType',
'pi.app_main.currentSliceReportCostType',
options[0].value,
options);
newSelector.id = 'costs-histogram-cost-type';
oldSelector.parentElement.replaceChild(newSelector, oldSelector);
},
set currentSliceReportCostType(currentSliceReportCostType) {
this.updateCostsHistogram_();
},
updateCostsHistogram_: function() {
var container = this.shadowRoot.querySelector(
'#costs-histogram-container');
if (this.$.table.selectedTableRow === undefined) {
container.style.display = 'none';
return;
}
container.style.display = '';
var selector = this.shadowRoot.querySelector(
'#costs-histogram-cost-type');
var func = selector.selectedItem.func;
var histogram = tr.b.u.Histogram.createLinear(
tr.b.u.Units.timeDurationInMs,
tr.b.Range.fromExplicitRange(0, 100),
100);
this.$.table.selectedTableRow.data.forEach(function(datum) {
var value = func(datum);
histogram.add(value, datum.runInfo);
});
var histogramSpan = this.shadowRoot.querySelector('#costs-histogram');
histogramSpan.histogram = histogram;
this.onBrushedBinsChanged_();
},
onBrushedBinsChanged_: function() {
var histogramSpan = this.shadowRoot.querySelector('#costs-histogram');
var brushedBins = histogramSpan.brushedBins;
var urlSet = {};
brushedBins.forEach(function(bin) {
bin.sourceInfos.forEach(function(sourceInfo) {
urlSet[sourceInfo.url] = 1;
});
});
urlSet = Object.keys(urlSet);
urlSet.sort();
this.$.links.setTraceUrls(urlSet);
}
});
</script>
</polymer-element>