blob: bc9586f2692c6f79e9e0ffb6f82bfacf6500998b [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2016 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/base/iteration_helpers.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.exportTo('tr.v', function() {
class ValueSet {
constructor(opt_values) {
this.values_ = new Map();
if (opt_values !== undefined)
for (var value of opt_values)
this.addHistogram(value);
}
get valueDicts() {
return this.map(v => v.asDict());
}
lookup(guid) {
return this.values_.get(guid);
}
get length() {
return this.values_.size;
}
toArray() {
return [...this];
}
*[Symbol.iterator]() {
for (var [guid, value] of this.values_)
yield value;
}
/**
* @param {!function(!tr.v.Histogram):*} callback
* @param {*=} opt_this
*/
map(callback, opt_this) {
return this.toArray().map(callback, opt_this || this);
}
/**
* Convert Values from dicts and add them.
* Resolve RelatedValueSet references.
*
* @param {Array.<Object>} dicts
*/
addValuesFromDicts(dicts) {
for (var dict of dicts)
this.addHistogram(tr.v.Histogram.fromDict(dict));
// Now resolve the RelatedValueSet references between values.
// This resolution process must wait until all new values are added in
// case a value refers to another that comes after it in dicts.
// Iterate over all values, old and new, in case an old value contained a
// reference to a new value. Don't worry, resolve() is idempotent.
// The expected running time is this: for each value (hundreds to
// thousands?), for each diagnostic that is a RelatedValueSet (0-5?), for
// each ValueRef (0-10?), do a hash lookup (constant time?).
for (var value of this) {
for (var [name, diagnostic] of value.diagnostics) {
if ((diagnostic instanceof tr.v.d.RelatedValueSet) ||
(diagnostic instanceof tr.v.d.RelatedValueMap)) {
diagnostic.resolve(this);
}
}
// In addition to Values, we must also look inside of Histogram samples.
for (var bin of value.allBins) {
for (var dm of bin.diagnosticMaps) {
for (var [name, diagnostic] of dm) {
if ((diagnostic instanceof tr.v.d.RelatedValueSet) ||
(diagnostic instanceof tr.v.d.RelatedValueMap)) {
diagnostic.resolve(this);
}
}
}
}
}
}
/**
* Find the Values that are not contained in any other Values'
* RelatedValueSet or RelatedValueMap diagnostics.
*
* @return {!Array.<!tr.v.Histogram>}
*/
get sourceValues() {
var sourceValues = new Map(this.values_);
// If a Histogram is in a RelatedValueSet or RelatedValueMap, which can be
// owned either by Values or by numeric samples, then it is not a
// source Histogram.
function deleteSourceValues(diagnosticMap) {
for (var [name, diagnostic] of diagnosticMap) {
if (diagnostic instanceof tr.v.d.RelatedValueSet)
for (var relatedValue of diagnostic)
sourceValues.delete(relatedValue.guid);
else if (diagnostic instanceof tr.v.d.RelatedValueMap)
for (var [name, relatedValue] of diagnostic)
sourceValues.delete(relatedValue.guid);
}
}
for (var hist of this) {
deleteSourceValues(hist.diagnostics);
for (var b of hist.allBins) {
for (var dm of b.diagnosticMaps) {
deleteSourceValues(dm);
}
}
}
return [...sourceValues.values()];
}
getValuesNamed(name) {
return this.toArray().filter(h => h.name === name);
}
/**
* @param {!tr.v.Histogram} h
*/
addHistogram(h) {
if (this.values_.get(h.guid))
throw new Error('Cannot add same Histogram twice');
this.values_.set(h.guid, h);
}
}
// This does not contain storyGroupingKeys!
ValueSet.GROUPINGS = {
HISTOGRAM_NAME: {
key: 'histogramName',
label: 'name',
dataFn: v => v.name
},
BENCHMARK_NAME: {
key: 'benchmarkName',
label: 'benchmark',
dataFn: v => tr.v.d.IterationInfo.getField(v, 'benchmarkName', '')
},
BENCHMARK_START: {
key: 'benchmarkStart',
label: 'time',
dataFn: v => tr.v.d.IterationInfo.getField(v, 'benchmarkStartString', '')
},
STORYSET_REPEAT: {
key: 'storysetRepeat',
label: 'storyset repeat',
dataFn: v => tr.v.d.IterationInfo.getField(
v, 'storysetRepeatCounterLabel', 0)
},
STORY_REPEAT: {
key: 'storyRepeat',
label: 'story repeat',
dataFn: v => tr.v.d.IterationInfo.getField(
v, 'storyRepeatCounterLabel', 0)
},
STORY_NAME: {
key: 'storyName',
label: 'story',
dataFn: v => tr.v.d.IterationInfo.getField(v, 'storyDisplayName', '')
},
DISPLAY_LABEL: {
key: 'displayLabel',
label: 'label',
dataFn: v => tr.v.d.IterationInfo.getField(v, 'displayLabel', 'Value')
}
};
return {
ValueSet: ValueSet
};
});
</script>