Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: tracing/tracing/value/numeric.html

Issue 2162963002: [polymer] Merge of master into polymer10-migration (Closed) Base URL: git@github.com:catapult-project/catapult.git@polymer10-migration
Patch Set: Merge polymer10-migration int polymer10-merge Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <!-- 2 <!--
3 Copyright 2016 The Chromium Authors. All rights reserved. 3 Copyright 2016 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be 4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file. 5 found in the LICENSE file.
6 --> 6 -->
7 7
8 <link rel="import" href="/tracing/base/iteration_helpers.html"> 8 <link rel="import" href="/tracing/base/iteration_helpers.html">
9 <link rel="import" href="/tracing/base/range.html"> 9 <link rel="import" href="/tracing/base/range.html">
10 <link rel="import" href="/tracing/base/running_statistics.html"> 10 <link rel="import" href="/tracing/base/running_statistics.html">
11 <link rel="import" href="/tracing/base/sorted_array_utils.html"> 11 <link rel="import" href="/tracing/base/sorted_array_utils.html">
12 <link rel="import" href="/tracing/base/statistics.html"> 12 <link rel="import" href="/tracing/base/statistics.html">
13 <link rel="import" href="/tracing/value/unit.html"> 13 <link rel="import" href="/tracing/value/unit.html">
14 14
15 <script> 15 <script>
16 'use strict'; 16 'use strict';
17 17
18 tr.exportTo('tr.v', function() { 18 tr.exportTo('tr.v', function() {
19 var Range = tr.b.Range; 19 var Range = tr.b.Range;
20 20
21 var MAX_SOURCE_INFOS = 16; 21 var MAX_DIAGNOSTICS = 16;
22
23 // p-values less than this indicate statistical significance.
24 var DEFAULT_ALPHA = 0.05;
25
26 /** @enum */
27 var Significance = {
28 DONT_CARE: -1,
29 INSIGNIFICANT: 0,
30 SIGNIFICANT: 1
31 };
22 32
23 function NumericBase(unit) { 33 function NumericBase(unit) {
24 if (!(unit instanceof tr.v.Unit)) 34 if (!(unit instanceof tr.v.Unit))
25 throw new Error('Expected provided unit to be instance of Unit'); 35 throw new Error('Expected provided unit to be instance of Unit');
26 36
27 this.unit = unit; 37 this.unit = unit;
28 } 38 }
29 39
30 NumericBase.prototype = { 40 NumericBase.prototype = {
41 merge: function(other) {
42 if (this.unit !== other.unit)
43 throw new Error('Merging Numerics with different units');
44
45 // Two Numerics that were built using the same NumericBuilder
46 // can be merged using addNumeric().
47 if (this instanceof Numeric && other instanceof Numeric &&
48 this.canAddNumeric(other)) {
49 var result = this.clone();
50 result.addNumeric(other.clone());
51 return result;
52 }
53
54 // Either a Scalar and a Numeric, or two Scalars...
55 // or two Numerics that were not built using the same NumericBuilder,
56 // should be built from their raw samples.
57 var samples = [];
58 this.sampleValuesInto(samples);
59 other.sampleValuesInto(samples);
60 return Numeric.buildFromSamples(this.unit, samples);
61 },
62
63 sampleValuesInto: function(samples) {
64 throw new Error('Not implemented');
65 },
66
31 asDict: function() { 67 asDict: function() {
32 var d = { 68 var d = {
33 unit: this.unit.asJSON() 69 unit: this.unit.asJSON()
34 }; 70 };
35 71
36 this.asDictInto_(d); 72 this.asDictInto_(d);
37 return d; 73 return d;
38 } 74 }
39 }; 75 };
40 76
41 NumericBase.fromDict = function(d) { 77 NumericBase.fromDict = function(d) {
42 if (d.type === 'scalar') 78 if (d.type === 'scalar')
43 return ScalarNumeric.fromDict(d); 79 return ScalarNumeric.fromDict(d);
44 80
45 if (d.type === 'numeric') 81 if (d.type === 'numeric')
46 return Numeric.fromDict(d); 82 return Numeric.fromDict(d);
47 83
48 throw new Error('Not implemented'); 84 throw new Error('Not implemented');
49 }; 85 };
50 86
51 function NumericBin(parentNumeric, opt_range) { 87 function NumericBin(parentNumeric, opt_range) {
52 this.parentNumeric = parentNumeric; 88 this.parentNumeric = parentNumeric;
53 this.range = opt_range || (new tr.b.Range()); 89 this.range = opt_range || (new tr.b.Range());
54 this.count = 0; 90 this.count = 0;
55 this.sourceInfos = []; 91 this.diagnostics = [];
56 } 92 }
57 93
58 NumericBin.fromDict = function(parentNumeric, d) { 94 NumericBin.fromDict = function(parentNumeric, d) {
59 var n = new NumericBin(parentNumeric); 95 var n = new NumericBin(parentNumeric);
60 n.range.min = d.min; 96 n.range.min = d.min;
61 n.range.max = d.max; 97 n.range.max = d.max;
62 n.count = d.count; 98 n.count = d.count;
63 n.sourceInfos = d.sourceInfos; 99 if (d.diagnostics)
100 n.diagnostics = d.diagnostics.map(dd => tr.v.d.Diagnostic.fromDict(dd));
64 return n; 101 return n;
65 }; 102 };
66 103
67 NumericBin.prototype = { 104 NumericBin.prototype = {
68 add: function(value, sourceInfo) { 105 /**
106 * @param {*} value
107 * @param {!tr.v.d.Diagnostic=} opt_diagnostic
108 */
109 add: function(value, opt_diagnostic) {
69 this.count += 1; 110 this.count += 1;
70 tr.b.Statistics.uniformlySampleStream(this.sourceInfos, this.count, 111 if (opt_diagnostic) {
71 sourceInfo, MAX_SOURCE_INFOS); 112 tr.b.Statistics.uniformlySampleStream(
113 this.diagnostics, this.count, opt_diagnostic, MAX_DIAGNOSTICS);
114 }
72 }, 115 },
73 116
74 addBin: function(other) { 117 addBin: function(other) {
75 if (!this.range.equals(other.range)) 118 if (!this.range.equals(other.range))
76 throw new Error('Merging incompatible Numeric bins.'); 119 throw new Error('Merging incompatible Numeric bins.');
77 tr.b.Statistics.mergeSampledStreams(this.sourceInfos, this.count, 120 tr.b.Statistics.mergeSampledStreams(this.diagnostics, this.count,
78 other.sourceInfos, other.count, MAX_SOURCE_INFOS); 121 other.diagnostics, other.count, MAX_DIAGNOSTICS);
79 this.count += other.count; 122 this.count += other.count;
80 }, 123 },
81 124
82 asDict: function() { 125 asDict: function() {
83 return { 126 return {
84 min: this.range.min, 127 min: this.range.min,
85 max: this.range.max, 128 max: this.range.max,
86 count: this.count, 129 count: this.count,
87 sourceInfos: this.sourceInfos.slice(0) 130 diagnostics: this.diagnostics.map(d => d.asDict())
88 }; 131 };
89 }, 132 },
90 133
91 asJSON: function() { 134 asJSON: function() {
92 return this.asDict(); 135 return this.asDict();
93 } 136 }
94 }; 137 };
95 138
96 function Numeric(unit, range, binInfo) { 139 function Numeric(unit, range, binInfo) {
97 NumericBase.call(this, unit); 140 NumericBase.call(this, unit);
98 141
99 this.range = range; 142 this.range = range;
100 143
101 this.numNans = 0; 144 this.numNans = 0;
102 this.nanSourceInfos = []; 145 this.nanDiagnostics = [];
103 146
104 this.running = new tr.b.RunningStatistics(); 147 this.running = new tr.b.RunningStatistics();
105 this.maxCount_ = 0; 148 this.maxCount_ = 0;
106 149
107 this.underflowBin = binInfo.underflowBin; 150 this.underflowBin = binInfo.underflowBin;
108 this.centralBins = binInfo.centralBins; 151 this.centralBins = binInfo.centralBins;
109 this.overflowBin = binInfo.overflowBin; 152 this.overflowBin = binInfo.overflowBin;
110 153
111 this.allBins = []; 154 this.allBins = [];
112 this.allBins.push(this.underflowBin); 155 this.allBins.push(this.underflowBin);
113 this.allBins.push.apply(this.allBins, this.centralBins); 156 this.allBins.push.apply(this.allBins, this.centralBins);
114 this.allBins.push(this.overflowBin); 157 this.allBins.push(this.overflowBin);
115 158
116 this.allBins.forEach(function(bin) { 159 this.allBins.forEach(function(bin) {
117 if (bin.count > this.maxCount_) 160 if (bin.count > this.maxCount_)
118 this.maxCount_ = bin.count; 161 this.maxCount_ = bin.count;
119 }, this); 162 }, this);
120 163
164 this.sampleValues_ = [];
165 this.maxNumSampleValues = this.allBins.length * 10;
166
121 this.summaryOptions = this.defaultSummaryOptions(); 167 this.summaryOptions = this.defaultSummaryOptions();
122 } 168 }
123 169
124 Numeric.fromDict = function(d) { 170 Numeric.fromDict = function(d) {
125 var range = Range.fromExplicitRange(d.min, d.max); 171 var range = Range.fromExplicitRange(d.min, d.max);
126 var binInfo = {}; 172 var binInfo = {};
127 binInfo.underflowBin = NumericBin.fromDict(undefined, d.underflowBin); 173 binInfo.underflowBin = NumericBin.fromDict(undefined, d.underflowBin);
128 binInfo.centralBins = d.centralBins.map(function(binAsDict) { 174 binInfo.centralBins = d.centralBins.map(function(binAsDict) {
129 return NumericBin.fromDict(undefined, binAsDict); 175 return NumericBin.fromDict(undefined, binAsDict);
130 }); 176 });
131 binInfo.overflowBin = NumericBin.fromDict(undefined, d.overflowBin); 177 binInfo.overflowBin = NumericBin.fromDict(undefined, d.overflowBin);
132 var n = new Numeric(tr.v.Unit.fromJSON(d.unit), range, binInfo); 178 var n = new Numeric(tr.v.Unit.fromJSON(d.unit), range, binInfo);
133 n.allBins.forEach(function(bin) { 179 n.allBins.forEach(function(bin) {
134 bin.parentNumeric = n; 180 bin.parentNumeric = n;
135 }); 181 });
136 if (d.running) 182 if (d.running)
137 n.running = tr.b.RunningStatistics.fromDict(d.running); 183 n.running = tr.b.RunningStatistics.fromDict(d.running);
138 if (d.summaryOptions) 184 if (d.summaryOptions)
139 n.customizeSummaryOptions(d.summaryOptions); 185 n.customizeSummaryOptions(d.summaryOptions);
140 n.numNans = d.numNans; 186 n.numNans = d.numNans;
141 n.nanSourceInfos = d.nanSourceInfos; 187 if (d.nanDiagnostics) {
188 n.nanDiagnostics = d.nanDiagnostics.map(
189 dd => tr.v.d.Diagnostic.fromDict(dd));
190 }
191 n.maxNumSampleValues = d.maxNumSampleValues;
192 n.sampleValues_ = d.sampleValues;
142 return n; 193 return n;
143 }; 194 };
144 195
196 /**
197 * @param {!tr.v.Unit} unit
198 * @param {!Array.<number>} samples
199 * @return {!Numeric}
200 */
201 Numeric.buildFromSamples = function(unit, samples) {
202 var range = new tr.b.Range();
203 // Prevent non-numeric samples from introducing NaNs into the range.
204 for (var sample of samples)
205 if (!isNaN(Math.max(sample)))
206 range.addValue(sample);
207
208 // NumericBuilder.addLinearBins() requires this.
209 if (range.isEmpty)
210 range.addValue(1);
211 if (range.min === range.max)
212 range.addValue(range.min - 1);
213
214 // This optimizes the resolution when samples are uniformly distributed
215 // (which is almost never the case).
216 var numBins = Math.ceil(Math.sqrt(samples.length));
217 var builder = new NumericBuilder(unit, range.min);
218 builder.addLinearBins(range.max, numBins);
219
220 var result = builder.build();
221 result.maxNumSampleValues = 1000;
222
223 // TODO(eakuefner): Propagate diagnostics?
224 for (var sample of samples)
225 result.add(sample);
226
227 return result;
228 };
229
145 Numeric.prototype = { 230 Numeric.prototype = {
146 __proto__: NumericBase.prototype, 231 __proto__: NumericBase.prototype,
147 232
148 get numValues() { 233 get numValues() {
149 return tr.b.Statistics.sum(this.allBins, function(e) { 234 return tr.b.Statistics.sum(this.allBins, function(e) {
150 return e.count; 235 return e.count;
151 }); 236 });
152 }, 237 },
153 238
154 get average() { 239 get average() {
155 return this.running.mean; 240 return this.running.mean;
156 }, 241 },
157 242
158 get sum() { 243 get sum() {
159 return this.running.sum; 244 return this.running.sum;
160 }, 245 },
161 246
162 get maxCount() { 247 get maxCount() {
163 return this.maxCount_; 248 return this.maxCount_;
164 }, 249 },
165 250
251 /**
252 * Requires that units agree.
253 * Returns DONT_CARE if that is the units' improvementDirection.
254 * Returns SIGNIFICANT if the Mann-Whitney U test returns a
255 * p-value less than opt_alpha or DEFAULT_ALPHA. Returns INSIGNIFICANT if
256 * the p-value is greater than alpha.
257 *
258 * @param {!tr.v.Numeric} other
259 * @param {number=} opt_alpha
260 * @return {!tr.v.Significance}
261 */
262 getDifferenceSignificance: function(other, opt_alpha) {
263 if (this.unit !== other.unit)
264 throw new Error('Cannot compare Numerics with different units');
265
266 if (this.unit.improvementDirection ===
267 tr.v.ImprovementDirection.DONT_CARE) {
268 return tr.v.Significance.DONT_CARE;
269 }
270
271 if (!(other instanceof Numeric))
272 throw new Error('Unable to compute a p-value');
273
274 var mwu = tr.b.Statistics.mwu.test(this.sampleValues, other.sampleValues);
275 if (mwu.p < (opt_alpha || DEFAULT_ALPHA))
276 return tr.v.Significance.SIGNIFICANT;
277 return tr.v.Significance.INSIGNIFICANT;
278 },
279
166 /* 280 /*
167 * Compute an approximation of percentile based on the counts in the bins. 281 * Compute an approximation of percentile based on the counts in the bins.
168 * If the real percentile lies within |this.range| then the result of 282 * If the real percentile lies within |this.range| then the result of
169 * the function will deviate from the real percentile by at most 283 * the function will deviate from the real percentile by at most
170 * the maximum width of the bin(s) within which the point(s) 284 * the maximum width of the bin(s) within which the point(s)
171 * from which the real percentile would be calculated lie. 285 * from which the real percentile would be calculated lie.
172 * If the real percentile is outside |this.range| then the function 286 * If the real percentile is outside |this.range| then the function
173 * returns the closest range limit: |this.range.min| or |this.range.max|. 287 * returns the closest range limit: |this.range.min| or |this.range.max|.
174 * 288 *
175 * @param {number} percent The percent must be between 0.0 and 1.0. 289 * @param {number} percent The percent must be between 0.0 and 1.0.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 return tr.b.lerp(value, lesserBin.count, greaterBin.count); 362 return tr.b.lerp(value, lesserBin.count, greaterBin.count);
249 }, 363 },
250 364
251 getBinForValue: function(value) { 365 getBinForValue: function(value) {
252 // Don't use subtraction to avoid arithmetic overflow. 366 // Don't use subtraction to avoid arithmetic overflow.
253 var binIndex = tr.b.findHighIndexInSortedArray( 367 var binIndex = tr.b.findHighIndexInSortedArray(
254 this.allBins, b => value < b.range.max ? -1 : 1); 368 this.allBins, b => value < b.range.max ? -1 : 1);
255 return this.allBins[binIndex] || this.overflowBin; 369 return this.allBins[binIndex] || this.overflowBin;
256 }, 370 },
257 371
258 add: function(value, sourceInfo) { 372 /**
373 * @param {*} value
374 * @param {!tr.v.d.Diagnostic=} opt_diagnostic
375 */
376 add: function(value, opt_diagnostic) {
259 if (typeof(value) !== 'number' || isNaN(value)) { 377 if (typeof(value) !== 'number' || isNaN(value)) {
260 this.numNans++; 378 this.numNans++;
261 tr.b.Statistics.uniformlySampleStream(this.nanSourceInfos, this.numNans, 379 if (opt_diagnostic) {
262 sourceInfo, MAX_SOURCE_INFOS); 380 tr.b.Statistics.uniformlySampleStream(this.nanDiagnostics,
263 return; 381 this.numNans, opt_diagnostic, MAX_DIAGNOSTICS);
382 }
383 } else {
384 var bin = this.getBinForValue(value);
385 bin.add(value, opt_diagnostic);
386 this.running.add(value);
387 if (bin.count > this.maxCount_)
388 this.maxCount_ = bin.count;
264 } 389 }
265 390
266 var bin = this.getBinForValue(value); 391 tr.b.Statistics.uniformlySampleStream(this.sampleValues_,
267 bin.add(value, sourceInfo); 392 this.numValues + this.numNans, value, this.maxNumSampleValues);
268 this.running.add(value);
269 if (bin.count > this.maxCount_)
270 this.maxCount_ = bin.count;
271 }, 393 },
272 394
395 sampleValuesInto: function(samples) {
396 for (var sampleValue of this.sampleValues)
397 samples.push(sampleValue);
398 },
399
400 /**
401 * Return true if this Numeric can be added to |other|.
402 *
403 * @param {!tr.v.Numeric} other
404 * @return {boolean}
405 */
406 canAddNumeric: function(other) {
407 if (!this.range.equals(other.range))
408 return false;
409 if (this.unit !== other.unit)
410 return false;
411 if (this.allBins.length !== other.allBins.length)
412 return false;
413
414 for (var i = 0; i < this.allBins.length; ++i)
415 if (!this.allBins[i].range.equals(other.allBins[i].range))
416 return false;
417
418 return true;
419 },
420
421 /**
422 * Add |other| to this Numeric in-place if they can be added.
423 *
424 * @param {!tr.v.Numeric} other
425 */
273 addNumeric: function(other) { 426 addNumeric: function(other) {
274 if (!this.range.equals(other.range) || 427 if (!this.canAddNumeric(other))
275 !this.unit === other.unit ||
276 this.allBins.length !== other.allBins.length) {
277 throw new Error('Merging incompatible Numerics.'); 428 throw new Error('Merging incompatible Numerics.');
278 } 429
279 tr.b.Statistics.mergeSampledStreams(this.nanSourceInfos, this.numNans, 430 tr.b.Statistics.mergeSampledStreams(this.nanDiagnostics, this.numNans,
280 other.nanSourceInfos, other.numNans, MAX_SOURCE_INFOS); 431 other.nanDiagnostics, other.numNans, MAX_DIAGNOSTICS);
432 tr.b.Statistics.mergeSampledStreams(
433 this.sampleValues, this.numValues,
434 other.sampleValues, other.numValues, tr.b.Statistics.mean(
435 [this.maxNumSampleValues, other.maxNumSampleValues]));
281 this.numNans += other.numNans; 436 this.numNans += other.numNans;
282 this.running = this.running.merge(other.running); 437 this.running = this.running.merge(other.running);
283 for (var i = 0; i < this.allBins.length; ++i) { 438 for (var i = 0; i < this.allBins.length; ++i) {
284 this.allBins[i].addBin(other.allBins[i]); 439 this.allBins[i].addBin(other.allBins[i]);
285 } 440 }
286 }, 441 },
287 442
288 /** 443 /**
289 * Controls which statistics are exported to dashboard for this numeric. 444 * Controls which statistics are exported to dashboard for this numeric.
290 * The |summaryOptions| parameter is a dictionary with optional boolean 445 * The |summaryOptions| parameter is a dictionary with optional boolean
291 * fields |count|, |sum|, |avg|, |std|, |min|, |max| and an optional 446 * fields |count|, |sum|, |avg|, |std|, |min|, |max| and an optional
292 * array field |percentile|. 447 * array field |percentile|.
293 * Each percentile should be a number between 0.0 and 1.0. 448 * Each percentile should be a number between 0.0 and 1.0.
294 * The options not included in the |summaryOptions| will not change. 449 * The options not included in the |summaryOptions| will not change.
295 */ 450 */
296 customizeSummaryOptions: function(summaryOptions) { 451 customizeSummaryOptions: function(summaryOptions) {
297 tr.b.iterItems(summaryOptions, function(key, value) { 452 tr.b.iterItems(summaryOptions, function(key, value) {
298 this.summaryOptions[key] = value; 453 this.summaryOptions[key] = value;
299 }, this); 454 }, this);
300 }, 455 },
301 456
302 defaultSummaryOptions: function() { 457 defaultSummaryOptions: function() {
303 return { 458 return {
304 count: true, 459 count: true,
305 sum: true, 460 sum: true,
306 avg: true, 461 avg: true,
307 std: true, 462 std: true,
308 min: true, 463 min: true,
309 max: true, 464 max: true,
465 nans: false,
310 percentile: [] 466 percentile: []
311 }; 467 };
312 }, 468 },
313 469
314 /** 470 /**
315 * Returns an array of {name: string, scalar: ScalarNumeric} values. 471 * Returns an array of {name: string, scalar: ScalarNumeric} values.
316 * Each enabled summary option produces the corresponding value: 472 * Each enabled summary option produces the corresponding value:
317 * min, max, count, sum, avg, or std. 473 * min, max, count, sum, avg, or std.
318 * Each percentile 0.x produces pct_0x0. 474 * Each percentile 0.x produces pct_0x0.
319 * Each percentile 0.xx produces pct_0xx. 475 * Each percentile 0.xx produces pct_0xx.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 if (!option) 514 if (!option)
359 return; 515 return;
360 if (stat === 'percentile') { 516 if (stat === 'percentile') {
361 option.forEach(function(percent) { 517 option.forEach(function(percent) {
362 var percentile = this.getApproximatePercentile(percent); 518 var percentile = this.getApproximatePercentile(percent);
363 results.push({ 519 results.push({
364 name: 'pct_' + percentToString(percent), 520 name: 'pct_' + percentToString(percent),
365 scalar: new tr.v.ScalarNumeric(this.unit, percentile) 521 scalar: new tr.v.ScalarNumeric(this.unit, percentile)
366 }); 522 });
367 }, this); 523 }, this);
524 } else if (stat === 'nans') {
525 results.push({
526 name: 'nans',
527 scalar: new tr.v.ScalarNumeric(
528 tr.v.Unit.byName.count_smallerIsBetter, this.numNans)
529 });
368 } else { 530 } else {
369 var statUnit = stat === 'count' ? 531 var statUnit = stat === 'count' ?
370 tr.v.Unit.byName.unitlessNumber_smallerIsBetter : this.unit; 532 tr.v.Unit.byName.count_smallerIsBetter : this.unit;
371 var key = statNameToKey(stat); 533 var key = statNameToKey(stat);
372 var statValue = this.running[key]; 534 var statValue = this.running[key];
373 if (typeof(statValue) === 'number') { 535 if (typeof(statValue) === 'number') {
374 results.push({ 536 results.push({
375 name: stat, 537 name: stat,
376 scalar: new tr.v.ScalarNumeric(statUnit, statValue) 538 scalar: new tr.v.ScalarNumeric(statUnit, statValue)
377 }); 539 });
378 } 540 }
379 } 541 }
380 }, this); 542 }, this);
381 return results; 543 return results;
382 }, 544 },
383 545
546 get sampleValues() {
547 return this.sampleValues_;
548 },
549
384 clone: function() { 550 clone: function() {
385 return Numeric.fromDict(this.asDict()); 551 return Numeric.fromDict(this.asDict());
386 }, 552 },
387 553
388 asDict: function() { 554 asDict: function() {
389 var d = { 555 var d = {
390 unit: this.unit.asJSON(), 556 unit: this.unit.asJSON(),
391 type: 'numeric', 557 type: 'numeric',
392 558
393 min: this.range.min, 559 min: this.range.min,
394 max: this.range.max, 560 max: this.range.max,
395 561
396 numNans: this.numNans, 562 numNans: this.numNans,
397 nanSourceInfos: this.nanSourceInfos, 563 nanDiagnostics: this.nanDiagnostics.map(d => d.asDict()),
398 564
399 running: this.running.asDict(), 565 running: this.running.asDict(),
400 summaryOptions: this.summaryOptions, 566 summaryOptions: this.summaryOptions,
401 567
568 sampleValues: this.sampleValues,
569 maxNumSampleValues: this.maxNumSampleValues,
402 underflowBin: this.underflowBin.asDict(), 570 underflowBin: this.underflowBin.asDict(),
403 centralBins: this.centralBins.map(function(bin) { 571 centralBins: this.centralBins.map(function(bin) {
404 return bin.asDict(); 572 return bin.asDict();
405 }), 573 }),
406 overflowBin: this.overflowBin.asDict() 574 overflowBin: this.overflowBin.asDict()
407 }; 575 };
408 return d; 576 return d;
409 }, 577 },
410 578
411 asJSON: function() { 579 asJSON: function() {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 * @param {number} nextBinBoundary The last added bin boundary (must be 669 * @param {number} nextBinBoundary The last added bin boundary (must be
502 * greater than |this.maxMinBoundary|). 670 * greater than |this.maxMinBoundary|).
503 * @param {number} binCount Number of bins to be added (must be positive). 671 * @param {number} binCount Number of bins to be added (must be positive).
504 */ 672 */
505 addLinearBins: function(nextMaxBinBoundary, binCount) { 673 addLinearBins: function(nextMaxBinBoundary, binCount) {
506 if (binCount <= 0) 674 if (binCount <= 0)
507 throw new Error('Bin count must be positive'); 675 throw new Error('Bin count must be positive');
508 676
509 var curMaxBinBoundary = this.maxBinBoundary; 677 var curMaxBinBoundary = this.maxBinBoundary;
510 if (curMaxBinBoundary >= nextMaxBinBoundary) { 678 if (curMaxBinBoundary >= nextMaxBinBoundary) {
511 throw new Error('The last added max boundary must be greater than ' + 679 throw new Error('The new max bin boundary must be greater than ' +
512 'the current max boundary boundary'); 680 'the previous max bin boundary');
513 } 681 }
514 682
515 var binWidth = (nextMaxBinBoundary - curMaxBinBoundary) / binCount; 683 var binWidth = (nextMaxBinBoundary - curMaxBinBoundary) / binCount;
516 for (var i = 1; i < binCount; i++) 684 for (var i = 1; i < binCount; i++)
517 this.addBinBoundary(curMaxBinBoundary + i * binWidth); 685 this.addBinBoundary(curMaxBinBoundary + i * binWidth);
518 this.addBinBoundary(nextMaxBinBoundary); 686 this.addBinBoundary(nextMaxBinBoundary);
519 687
520 return this; 688 return this;
521 }, 689 },
522 690
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 numeric.allBins.forEach(function(bin) { 762 numeric.allBins.forEach(function(bin) {
595 bin.parentNumeric = numeric; 763 bin.parentNumeric = numeric;
596 }); 764 });
597 return numeric; 765 return numeric;
598 } 766 }
599 }; 767 };
600 768
601 /** 769 /**
602 * Create a linearly scaled tr.v.NumericBuilder with |numBins| bins ranging 770 * Create a linearly scaled tr.v.NumericBuilder with |numBins| bins ranging
603 * from |range.min| to |range.max|. 771 * from |range.min| to |range.max|.
772 *
773 * @param {!tr.v.Unit} unit
774 * @param {!tr.b.Range} range
775 * @param {number} numBins
776 * @return {tr.v.NumericBuilder}
604 */ 777 */
605 NumericBuilder.createLinear = function(unit, range, numBins) { 778 NumericBuilder.createLinear = function(unit, range, numBins) {
606 if (range.isEmpty) 779 if (range.isEmpty)
607 throw new Error('Range must be non-empty'); 780 throw new Error('Range must be non-empty');
608 return new NumericBuilder(unit, range.min).addLinearBins( 781 return new NumericBuilder(unit, range.min).addLinearBins(
609 range.max, numBins); 782 range.max, numBins);
610 }; 783 };
611 784
785 /**
786 * Create an exponentially scaled tr.v.NumericBuilder with |numBins| bins
787 * ranging from |range.min| to |range.max|.
788 *
789 * @param {!tr.v.Unit} unit
790 * @param {!tr.b.Range} range
791 * @param {number} numBins
792 * @return {tr.v.NumericBuilder}
793 */
794 NumericBuilder.createExponential = function(unit, range, numBins) {
795 if (range.isEmpty)
796 throw new Error('Range must be non-empty');
797 return new NumericBuilder(unit, range.min).addExponentialBins(
798 range.max, numBins);
799 };
800
612 function ScalarNumeric(unit, value) { 801 function ScalarNumeric(unit, value) {
802 if (!(unit instanceof tr.v.Unit))
803 throw new Error('Expected Unit');
804
613 if (!(typeof(value) == 'number')) 805 if (!(typeof(value) == 'number'))
614 throw new Error('Expected value to be number'); 806 throw new Error('Expected value to be number');
615 807
616 NumericBase.call(this, unit); 808 NumericBase.call(this, unit);
617 this.value = value; 809 this.value = value;
618 } 810 }
619 811
620 ScalarNumeric.prototype = { 812 ScalarNumeric.prototype = {
621 __proto__: NumericBase.prototype, 813 __proto__: NumericBase.prototype,
622 814
623 asDictInto_: function(d) { 815 asDictInto_: function(d) {
624 d.type = 'scalar'; 816 d.type = 'scalar';
625 817
626 // Infinity and NaN are left out of JSON for security reasons that do not 818 // Infinity and NaN are left out of JSON for security reasons that do not
627 // apply to our use cases. 819 // apply to our use cases.
628 if (this.value === Infinity) 820 if (this.value === Infinity)
629 d.value = 'Infinity'; 821 d.value = 'Infinity';
630 else if (this.value === -Infinity) 822 else if (this.value === -Infinity)
631 d.value = '-Infinity'; 823 d.value = '-Infinity';
632 else if (isNaN(this.value)) 824 else if (isNaN(this.value))
633 d.value = 'NaN'; 825 d.value = 'NaN';
634 else 826 else
635 d.value = this.value; 827 d.value = this.value;
636 }, 828 },
637 829
830 sampleValuesInto: function(samples) {
831 samples.push(this.value);
832 },
833
638 toString: function() { 834 toString: function() {
639 return this.unit.format(this.value); 835 return this.unit.format(this.value);
640 } 836 }
641 }; 837 };
642 838
643 ScalarNumeric.fromDict = function(d) { 839 ScalarNumeric.fromDict = function(d) {
644 // Infinity and NaN are left out of JSON for security reasons that do not 840 // Infinity and NaN are left out of JSON for security reasons that do not
645 // apply to our use cases. 841 // apply to our use cases.
646 if (typeof(d.value) === 'string') { 842 if (typeof(d.value) === 'string') {
647 if (d.value === '-Infinity') { 843 if (d.value === '-Infinity') {
648 d.value = -Infinity; 844 d.value = -Infinity;
649 } else if (d.value === 'Infinity') { 845 } else if (d.value === 'Infinity') {
650 d.value = Infinity; 846 d.value = Infinity;
651 } else if (d.value === 'NaN') { 847 } else if (d.value === 'NaN') {
652 d.value = NaN; 848 d.value = NaN;
653 } 849 }
654 } 850 }
655 851
656 return new ScalarNumeric(tr.v.Unit.fromJSON(d.unit), d.value); 852 return new ScalarNumeric(tr.v.Unit.fromJSON(d.unit), d.value);
657 }; 853 };
658 854
659 return { 855 return {
856 Significance: Significance,
660 NumericBase: NumericBase, 857 NumericBase: NumericBase,
661 NumericBin: NumericBin, 858 NumericBin: NumericBin,
662 Numeric: Numeric, 859 Numeric: Numeric,
663 NumericBuilder: NumericBuilder, 860 NumericBuilder: NumericBuilder,
664 ScalarNumeric: ScalarNumeric 861 ScalarNumeric: ScalarNumeric
665 }; 862 };
666 }); 863 });
667 </script> 864 </script>
OLDNEW
« no previous file with comments | « tracing/tracing/value/diagnostics/related_value_map.html ('k') | tracing/tracing/value/numeric_test.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698