blob: 86a3765fbfe503f7296f365710b7fec22af8b3cd [file] [edit]
<!DOCTYPE html>
<!--
Copyright 2017 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/value/histogram_set.html">
<script>
'use strict';
tr.exportTo('tr.v', function() {
/*
* See also HistogramSet.groupHistogramsRecursively().
* See also tr.v.ui.HistogramSetTableRow.
*/
class HistogramSetHierarchy {
/**
* @param {string} name
*/
constructor(name) {
this.name = name;
this.description = '';
this.depth = 0;
this.subRows = [];
this.columns = new Map();
}
* walk() {
yield this;
for (const row of this.subRows) yield* row.walk();
}
static* walkAll(rootRows) {
for (const rootRow of rootRows) yield* rootRow.walk();
}
/**
* Build table rows recursively from grouped Histograms.
*
* @param {!(HistogramArray|HistogramArrayMap)}
* @returns {!Array.<!HistogramSetHierarchy>}
*/
static build(histogramArrayMap) {
const rootRows = [];
HistogramSetHierarchy.buildInternal_(histogramArrayMap, [], rootRows);
const histograms = new tr.v.HistogramSet();
for (const row of HistogramSetHierarchy.walkAll(rootRows)) {
for (const hist of row.columns.values()) {
if (!(hist instanceof tr.v.Histogram)) continue;
histograms.addHistogram(hist);
}
}
histograms.deduplicateDiagnostics();
for (const row of HistogramSetHierarchy.walkAll(rootRows)) {
row.maybeRebin_();
}
return rootRows;
}
maybeRebin_() {
// if all of |this| row's columns are single-bin, then re-bin all of them.
const dataRange = new tr.b.math.Range();
for (const hist of this.columns.values()) {
if (!(hist instanceof tr.v.Histogram)) continue;
if (hist.allBins.length > 1) return; // don't re-bin
if (hist.numValues === 0) continue; // ignore hist
dataRange.addValue(hist.min);
dataRange.addValue(hist.max);
}
dataRange.addValue(tr.b.math.lesserWholeNumber(dataRange.min));
dataRange.addValue(tr.b.math.greaterWholeNumber(dataRange.max));
if (dataRange.min === dataRange.max) return; // don't rebin
const boundaries = tr.v.HistogramBinBoundaries.createLinear(
dataRange.min, dataRange.max, tr.v.DEFAULT_REBINNED_COUNT);
for (const [name, hist] of this.columns) {
if (!(hist instanceof tr.v.Histogram)) continue;
this.columns.set(name, hist.rebin(boundaries));
}
}
static mergeHistogramDownHierarchy_(histogram, hierarchy, columnName) {
// Track the path down the grouping tree to each Histogram,
// but only start tracking the path at the grouping level that
// corresponds to the Histogram NAME Grouping.
for (const row of hierarchy) {
if (!row.description) {
row.description = histogram.description;
}
const existing = row.columns.get(columnName);
if (existing === undefined) {
row.columns.set(columnName, histogram.clone());
continue;
}
if (existing instanceof tr.v.HistogramSet) {
// There have already been unmergeable histograms.
existing.addHistogram(histogram);
continue;
}
if (!existing.canAddHistogram(histogram)) {
// TODO(benjhayden) Remove?
const unmergeableHistograms = new tr.v.HistogramSet([histogram]);
row.columns.set(columnName, unmergeableHistograms);
continue;
}
existing.addHistogram(histogram);
}
}
static buildInternal_(
histogramArrayMap, hierarchy, rootRows) {
for (const [name, histograms] of histogramArrayMap) {
if (histograms instanceof Array) {
// This recursion base case corresponds to the recursion base case of
// groupHistogramsRecursively(). The last groupingCallback is always
// getDisplayLabel, which defines the columns of the table and is
// unskippable.
for (const histogram of histograms) {
HistogramSetHierarchy.mergeHistogramDownHierarchy_(
histogram, hierarchy, name);
}
} else if (histograms instanceof Map) {
// |histograms| is actually a nested histogramArrayMap.
const row = new HistogramSetHierarchy(name);
row.depth = hierarchy.length;
hierarchy.push(row);
HistogramSetHierarchy.buildInternal_(histograms, hierarchy, rootRows);
hierarchy.pop();
if (hierarchy.length === 0) {
rootRows.push(row);
} else {
const parentRow = hierarchy[hierarchy.length - 1];
parentRow.subRows.push(row);
}
}
}
}
}
return {HistogramSetHierarchy};
});
</script>