blob: 6599ee7f33840b687e9d6412a015c7a795527d0d [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/value/diagnostics/generic.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
let unitlessNumber = tr.b.Unit.byName.unitlessNumber;
let unitlessNumber_smallerIsBetter =
tr.b.Unit.byName.unitlessNumber_smallerIsBetter;
let TEST_BOUNDARIES = tr.v.HistogramBinBoundaries.createLinear(0, 1000, 10);
function checkBoundaries(boundaries, expectedMinBoundary, expectedMaxBoundary,
expectedUnit, expectedBinRanges) {
assert.strictEqual(boundaries.range.min, expectedMinBoundary);
assert.strictEqual(boundaries.range.max, expectedMaxBoundary);
// Check that the boundaries can be used multiple times.
for (let i = 0; i < 3; i++) {
let hist = new tr.v.Histogram('', expectedUnit, boundaries);
assert.instanceOf(hist, tr.v.Histogram);
assert.strictEqual(hist.unit, expectedUnit);
assert.strictEqual(hist.numValues, 0);
assert.lengthOf(hist.allBins, expectedBinRanges.length);
for (let j = 0; j < expectedBinRanges.length; j++) {
let bin = hist.allBins[j];
assert.strictEqual(bin.count, 0);
assert.isTrue(bin.range.equals(expectedBinRanges[j]));
}
}
}
test('getStatisticScalar', function() {
const hist = new tr.v.Histogram('', unitlessNumber);
// getStatisticScalar should work even when the statistics are disabled.
hist.customizeSummaryOptions({
avg: false,
count: false,
max: false,
min: false,
std: false,
sum: false,
});
assert.isUndefined(hist.getStatisticScalar('avg'));
assert.isUndefined(hist.getStatisticScalar('std'));
assert.strictEqual(0, hist.getStatisticScalar('geometricMean').value);
assert.strictEqual(Infinity, hist.getStatisticScalar('min').value);
assert.strictEqual(-Infinity, hist.getStatisticScalar('max').value);
assert.strictEqual(0, hist.getStatisticScalar('sum').value);
assert.strictEqual(0, hist.getStatisticScalar('nans').value);
assert.strictEqual(0, hist.getStatisticScalar('count').value);
assert.strictEqual(0, hist.getStatisticScalar('pct_000').value);
assert.strictEqual(0, hist.getStatisticScalar('pct_050').value);
assert.strictEqual(0, hist.getStatisticScalar('pct_100').value);
assert.isFalse(hist.canCompare());
assert.throws(() => hist.getStatisticScalar(tr.v.DELTA + 'avg'));
const ref = new tr.v.Histogram('', unitlessNumber);
for (let i = 0; i < 10; ++i) {
hist.addSample(i * 10);
ref.addSample(i);
}
assert.strictEqual(45, hist.getStatisticScalar('avg').value);
assert.closeTo(30.277, hist.getStatisticScalar('std').value, 1e-3);
assert.closeTo(0, hist.getStatisticScalar('geometricMean').value, 1e-4);
assert.strictEqual(0, hist.getStatisticScalar('min').value);
assert.strictEqual(90, hist.getStatisticScalar('max').value);
assert.strictEqual(450, hist.getStatisticScalar('sum').value);
assert.strictEqual(0, hist.getStatisticScalar('nans').value);
assert.strictEqual(10, hist.getStatisticScalar('count').value);
assert.closeTo(18.371, hist.getStatisticScalar('pct_025').value, 1e-3);
assert.closeTo(55.48, hist.getStatisticScalar('pct_075').value, 1e-3);
assert.strictEqual(40.5, hist.getStatisticScalar(
tr.v.DELTA + 'avg', ref).value);
assert.closeTo(27.249, hist.getStatisticScalar(
tr.v.DELTA + 'std', ref).value, 1e-3);
assert.closeTo(0, hist.getStatisticScalar(
tr.v.DELTA + 'geometricMean', ref).value, 1e-4);
assert.strictEqual(0, hist.getStatisticScalar(
tr.v.DELTA + 'min', ref).value);
assert.strictEqual(81, hist.getStatisticScalar(
tr.v.DELTA + 'max', ref).value);
assert.strictEqual(405, hist.getStatisticScalar(
tr.v.DELTA + 'sum', ref).value);
assert.strictEqual(0, hist.getStatisticScalar(
tr.v.DELTA + 'nans', ref).value);
assert.strictEqual(0, hist.getStatisticScalar(
tr.v.DELTA + 'count', ref).value);
assert.closeTo(16.357, hist.getStatisticScalar(
tr.v.DELTA + 'pct_025', ref).value, 1e-3);
assert.closeTo(49.396, hist.getStatisticScalar(
tr.v.DELTA + 'pct_075', ref).value, 1e-3);
assert.strictEqual(9, hist.getStatisticScalar(
`%${tr.v.DELTA}avg`, ref).value);
assert.closeTo(9, hist.getStatisticScalar(
`%${tr.v.DELTA}std`, ref).value, 1e-3);
assert.isTrue(isNaN(hist.getStatisticScalar(
`%${tr.v.DELTA}geometricMean`, ref).value));
assert.isTrue(isNaN(hist.getStatisticScalar(
`%${tr.v.DELTA}min`, ref).value));
assert.strictEqual(9, hist.getStatisticScalar(
`%${tr.v.DELTA}max`, ref).value);
assert.strictEqual(9, hist.getStatisticScalar(
`%${tr.v.DELTA}sum`, ref).value);
assert.isTrue(isNaN(hist.getStatisticScalar(
`%${tr.v.DELTA}nans`, ref).value));
assert.strictEqual(0, hist.getStatisticScalar(
`%${tr.v.DELTA}count`, ref).value);
assert.closeTo(8.12, hist.getStatisticScalar(
`%${tr.v.DELTA}pct_025`, ref).value, 1e-3);
assert.closeTo(8.12, hist.getStatisticScalar(
`%${tr.v.DELTA}pct_075`, ref).value, 1e-3);
});
test('rebin', function() {
let hist = new tr.v.Histogram('foo', unitlessNumber_smallerIsBetter,
tr.v.HistogramBinBoundaries.SINGULAR);
assert.strictEqual(400, hist.maxNumSampleValues);
for (let i = 0; i < 100; ++i) {
hist.addSample(i);
}
let rebinned = hist.rebin(TEST_BOUNDARIES);
assert.strictEqual(12, rebinned.allBins.length);
assert.strictEqual(100, rebinned.allBins[1].count);
assert.strictEqual(hist.numValues, rebinned.numValues);
assert.strictEqual(hist.average, rebinned.average);
assert.strictEqual(hist.standardDeviation, rebinned.standardDeviation);
assert.strictEqual(hist.geometricMean, rebinned.geometricMean);
assert.strictEqual(hist.sum, rebinned.sum);
assert.strictEqual(hist.min, rebinned.min);
assert.strictEqual(hist.max, rebinned.max);
for (let i = 100; i < 1000; ++i) {
hist.addSample(i);
}
rebinned = hist.rebin(TEST_BOUNDARIES);
assert.strictEqual(12, rebinned.allBins.length);
let binCountSum = 0;
for (let i = 1; i < 11; ++i) {
binCountSum += rebinned.allBins[i].count;
assert.isAbove(100, rebinned.allBins[i].count, i);
}
assert.strictEqual(400, binCountSum);
assert.strictEqual(hist.numValues, rebinned.numValues);
assert.strictEqual(hist.average, rebinned.average);
assert.strictEqual(hist.standardDeviation, rebinned.standardDeviation);
assert.strictEqual(hist.geometricMean, rebinned.geometricMean);
assert.strictEqual(hist.sum, rebinned.sum);
assert.strictEqual(hist.min, rebinned.min);
assert.strictEqual(hist.max, rebinned.max);
});
test('serializationSize', function() {
// Ensure that serialized Histograms don't take up too much more space than
// necessary.
let hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
// You can change these numbers, but when you do, please explain in your CL
// description why they changed.
let dict = hist.asDict();
assert.strictEqual(107, JSON.stringify(dict).length);
assert.isUndefined(dict.allBins);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
hist.addSample(100);
dict = hist.asDict();
assert.strictEqual(198, JSON.stringify(dict).length);
assert.isUndefined(dict.allBins.length);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
hist.addSample(100);
dict = hist.asDict();
// SAMPLE_VALUES grew by "100,"
assert.strictEqual(202, JSON.stringify(dict).length);
assert.isUndefined(dict.allBins.length);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
hist.addSample(271, {foo: new tr.v.d.Generic('bar')});
dict = hist.asDict();
assert.strictEqual(262, JSON.stringify(dict).length);
assert.isUndefined(dict.allBins.length);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
// Add samples to most bins so that allBinsArray is more efficient than
// allBinsDict.
for (let i = 10; i < 100; ++i) {
hist.addSample(10 * i);
}
dict = hist.asDict();
assert.strictEqual(691, JSON.stringify(hist.asDict()).length);
assert.lengthOf(dict.allBins, 12);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
// Lowering maxNumSampleValues takes a random sub-sample of the existing
// sampleValues. We have deliberately set all samples to 3-digit numbers so
// that the serialized size is constant regardless of which samples are
// retained.
hist.maxNumSampleValues = 10;
dict = hist.asDict();
assert.strictEqual(383, JSON.stringify(dict).length);
assert.lengthOf(dict.allBins, 12);
assert.deepEqual(dict, tr.v.Histogram.fromDict(dict).asDict());
});
test('significance', function() {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 10);
let histA = new tr.v.Histogram(
'', unitlessNumber_smallerIsBetter, boundaries);
let histB = new tr.v.Histogram(
'', unitlessNumber_smallerIsBetter, boundaries);
let dontCare = new tr.v.Histogram('', unitlessNumber, boundaries);
assert.strictEqual(dontCare.getDifferenceSignificance(dontCare),
tr.b.math.Statistics.Significance.DONT_CARE);
for (let i = 0; i < 100; ++i) {
histA.addSample(i);
histB.addSample(i * 0.85);
}
assert.strictEqual(histA.getDifferenceSignificance(histB),
tr.b.math.Statistics.Significance.INSIGNIFICANT);
assert.strictEqual(histB.getDifferenceSignificance(histA),
tr.b.math.Statistics.Significance.INSIGNIFICANT);
assert.strictEqual(histA.getDifferenceSignificance(histB, 0.1),
tr.b.math.Statistics.Significance.SIGNIFICANT);
assert.strictEqual(histB.getDifferenceSignificance(histA, 0.1),
tr.b.math.Statistics.Significance.SIGNIFICANT);
});
test('basic', function() {
let hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
assert.equal(hist.getBinForValue(250).range.min, 200);
assert.equal(hist.getBinForValue(250).range.max, 300);
hist.addSample(-1, {foo: new tr.v.d.Generic('a')});
hist.addSample(0, {foo: new tr.v.d.Generic('b')});
hist.addSample(0, {foo: new tr.v.d.Generic('c')});
hist.addSample(500, {foo: new tr.v.d.Generic('c')});
hist.addSample(999, {foo: new tr.v.d.Generic('d')});
hist.addSample(1000, {foo: new tr.v.d.Generic('d')});
assert.equal(hist.allBins[0].count, 1);
assert.equal(hist.getBinForValue(0).count, 2);
assert.deepEqual(
hist.getBinForValue(0).diagnosticMaps.map(dm => dm.get('foo').value),
['b', 'c']);
assert.equal(hist.getBinForValue(500).count, 1);
assert.equal(hist.getBinForValue(999).count, 1);
assert.equal(hist.allBins[hist.allBins.length - 1].count, 1);
assert.equal(hist.numValues, 6);
assert.closeTo(hist.average, 416.3, 0.1);
});
test('nans', function() {
let hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
hist.addSample(undefined, {foo: new tr.v.d.Generic('b')});
hist.addSample(NaN, {'foo': new tr.v.d.Generic('c')});
hist.addSample(undefined);
hist.addSample(NaN);
assert.equal(hist.numNans, 4);
assert.deepEqual(hist.nanDiagnosticMaps.map(dm => dm.get('foo').value),
['b', 'c']);
let hist2 = tr.v.Histogram.fromDict(hist.asDict());
assert.instanceOf(hist2.nanDiagnosticMaps[0], tr.v.d.DiagnosticMap);
assert.instanceOf(hist2.nanDiagnosticMaps[0].get('foo'), tr.v.d.Generic);
});
test('addHistogramsValid', function() {
let hist0 = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
let hist1 = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
hist0.addSample(-1, {foo: new tr.v.d.Generic('a0')});
hist0.addSample(0, {foo: new tr.v.d.Generic('b0')});
hist0.addSample(0, {foo: new tr.v.d.Generic('c0')});
hist0.addSample(500, {foo: new tr.v.d.Generic('c0')});
hist0.addSample(1000, {foo: new tr.v.d.Generic('d0')});
hist0.addSample(NaN, {foo: new tr.v.d.Generic('e0')});
hist1.addSample(-1, {foo: new tr.v.d.Generic('a1')});
hist1.addSample(0, {foo: new tr.v.d.Generic('b1')});
hist1.addSample(0, {foo: new tr.v.d.Generic('c1')});
hist1.addSample(999, {foo: new tr.v.d.Generic('d1')});
hist1.addSample(1000, {foo: new tr.v.d.Generic('d1')});
hist1.addSample(NaN, {foo: new tr.v.d.Generic('e1')});
hist0.addHistogram(hist1);
assert.equal(hist0.numNans, 2);
assert.deepEqual(hist0.nanDiagnosticMaps.map(dmd => dmd.get('foo').value),
['e0', 'e1']);
assert.equal(hist0.allBins[0].count, 2);
assert.deepEqual(
hist0.allBins[0].diagnosticMaps.map(dmd => dmd.get('foo').value),
['a0', 'a1']);
assert.equal(hist0.getBinForValue(0).count, 4);
assert.deepEqual(
hist0.getBinForValue(0).diagnosticMaps.map(dmd => dmd.get('foo').value),
['b0', 'c0', 'b1', 'c1']);
assert.equal(hist0.getBinForValue(500).count, 1);
assert.deepEqual(
hist0.getBinForValue(500).diagnosticMaps.map(dmd =>
dmd.get('foo').value),
['c0']);
assert.equal(hist0.getBinForValue(999).count, 1);
assert.deepEqual(
hist0.getBinForValue(999).diagnosticMaps.map(dmd =>
dmd.get('foo').value),
['d1']);
assert.equal(hist0.allBins[hist0.allBins.length - 1].count, 2);
assert.deepEqual(hist0.allBins[hist0.allBins.length - 1].diagnosticMaps.map(
dmd => dmd.get('foo').value), ['d0', 'd1']);
assert.equal(hist0.numValues, 10);
assert.closeTo(hist0.average, 349.7, 0.1);
let hist02 = tr.v.Histogram.fromDict(hist0.asDict());
assert.instanceOf(hist02.allBins[0].diagnosticMaps[0],
tr.v.d.DiagnosticMap);
assert.instanceOf(hist02.allBins[0].diagnosticMaps[0].get('foo'),
tr.v.d.Generic);
});
test('addHistogramsInvalid', function() {
let hist0 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
tr.v.HistogramBinBoundaries.createLinear(0, 1000, 10));
let hist1 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
tr.v.HistogramBinBoundaries.createLinear(0, 1001, 10));
let hist2 = new tr.v.Histogram('', tr.b.Unit.byName.timeDurationInMs,
tr.v.HistogramBinBoundaries.createLinear(0, 1000, 11));
assert.isFalse(hist0.canAddHistogram(hist1));
assert.isFalse(hist0.canAddHistogram(hist2));
assert.isFalse(hist1.canAddHistogram(hist0));
assert.isFalse(hist1.canAddHistogram(hist2));
assert.isFalse(hist2.canAddHistogram(hist0));
assert.isFalse(hist2.canAddHistogram(hist1));
assert.throws(hist0.addHistogram.bind(hist0, hist1), Error);
assert.throws(hist0.addHistogram.bind(hist0, hist2), Error);
});
test('addHistogramWithNonDiagnosticMapThrows', function() {
let hist = new tr.v.Histogram('', unitlessNumber, TEST_BOUNDARIES);
assert.throws(hist.addSample.bind(42, 'foo'), Error);
});
test('getApproximatePercentile', function() {
function check(array, min, max, bins, precision) {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(min, max, bins);
let hist = new tr.v.Histogram(
'', tr.b.Unit.byName.timeDurationInMs, boundaries);
array.forEach((x) => hist.addSample(x, {foo: new tr.v.d.Generic('x')}));
[0.25, 0.5, 0.75, 0.8, 0.95, 0.99].forEach(function(percent) {
let expected = tr.b.math.Statistics.percentile(array, percent);
let actual = hist.getApproximatePercentile(percent);
assert.closeTo(expected, actual, precision);
});
}
check([1, 2, 5, 7], 0.5, 10.5, 10, 1e-3);
check([3, 3, 4, 4], 0.5, 10.5, 10, 1e-3);
check([1, 10], 0.5, 10.5, 10, 1e-3);
check([1, 2, 3, 4, 5], 0.5, 10.5, 10, 1e-3);
check([3, 3, 3, 3, 3], 0.5, 10.5, 10, 1e-3);
check([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3);
check([1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10], 0.5, 10.5, 10, 1e-3);
check([0, 11], 0.5, 10.5, 10, 1);
check([0, 6, 11], 0.5, 10.5, 10, 1);
let array = [];
for (let i = 0; i < 1000; i++)
array.push((i * i) % 10 + 1);
check(array, 0.5, 10.5, 10, 1e-3);
// If the real percentile is outside the bin range then the approximation
// error can be high.
check([-10000], 0, 10, 10, 10000);
check([10000], 0, 10, 10, 10000 - 10);
// The result is no more than the bin width away from the real percentile.
check([1, 1], 0, 10, 1, 10);
});
test('histogramBinBoundaries_addBinBoundary', function() {
let b = new tr.v.HistogramBinBoundaries(-100);
b.addBinBoundary(50);
checkBoundaries(b, -100, 50, tr.b.Unit.byName.timeDurationInMs, [
tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
tr.b.math.Range.fromExplicitRange(-100, 50),
tr.b.math.Range.fromExplicitRange(50, Number.MAX_VALUE)
]);
b.addBinBoundary(60);
b.addBinBoundary(75);
checkBoundaries(b, -100, 75, tr.b.Unit.byName.timeDurationInMs, [
tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
tr.b.math.Range.fromExplicitRange(-100, 50),
tr.b.math.Range.fromExplicitRange(50, 60),
tr.b.math.Range.fromExplicitRange(60, 75),
tr.b.math.Range.fromExplicitRange(75, Number.MAX_VALUE)
]);
});
test('histogramBinBoundaries_addLinearBins', function() {
let b = new tr.v.HistogramBinBoundaries(1000);
b.addLinearBins(1200, 5);
checkBoundaries(b, 1000, 1200, tr.b.Unit.byName.powerInWatts, [
tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 1000),
tr.b.math.Range.fromExplicitRange(1000, 1040),
tr.b.math.Range.fromExplicitRange(1040, 1080),
tr.b.math.Range.fromExplicitRange(1080, 1120),
tr.b.math.Range.fromExplicitRange(1120, 1160),
tr.b.math.Range.fromExplicitRange(1160, 1200),
tr.b.math.Range.fromExplicitRange(1200, Number.MAX_VALUE)
]);
});
test('histogramBinBoundaries_addExponentialBins', function() {
let b = new tr.v.HistogramBinBoundaries(0.5);
b.addExponentialBins(8, 4);
checkBoundaries(b, 0.5, 8, tr.b.Unit.byName.energyInJoules, [
tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 0.5),
tr.b.math.Range.fromExplicitRange(0.5, 1),
tr.b.math.Range.fromExplicitRange(1, 2),
tr.b.math.Range.fromExplicitRange(2, 4),
tr.b.math.Range.fromExplicitRange(4, 8),
tr.b.math.Range.fromExplicitRange(8, Number.MAX_VALUE)
]);
});
test('histogramBinBoundaries_combined', function() {
let b = new tr.v.HistogramBinBoundaries(-273.15);
b.addBinBoundary(-50);
b.addLinearBins(4, 3);
b.addExponentialBins(16, 2);
b.addLinearBins(17, 4);
b.addBinBoundary(100);
checkBoundaries(b, -273.15, 100, tr.b.Unit.byName.unitlessNumber, [
tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -273.15),
tr.b.math.Range.fromExplicitRange(-273.15, -50),
tr.b.math.Range.fromExplicitRange(-50, -32),
tr.b.math.Range.fromExplicitRange(-32, -14),
tr.b.math.Range.fromExplicitRange(-14, 4),
tr.b.math.Range.fromExplicitRange(4, 8),
tr.b.math.Range.fromExplicitRange(8, 16),
tr.b.math.Range.fromExplicitRange(16, 16.25),
tr.b.math.Range.fromExplicitRange(16.25, 16.5),
tr.b.math.Range.fromExplicitRange(16.5, 16.75),
tr.b.math.Range.fromExplicitRange(16.75, 17),
tr.b.math.Range.fromExplicitRange(17, 100),
tr.b.math.Range.fromExplicitRange(100, Number.MAX_VALUE)
]);
});
test('histogramBinBoundaries_throws', function() {
let b0 = new tr.v.HistogramBinBoundaries(-7);
assert.throws(function() { b0.addBinBoundary(-10 /* must be > -7 */); });
assert.throws(function() { b0.addBinBoundary(-7 /* must be > -7 */); });
assert.throws(function() { b0.addLinearBins(-10 /* must be > -7 */, 10); });
assert.throws(function() { b0.addLinearBins(-7 /* must be > -7 */, 100); });
assert.throws(function() { b0.addLinearBins(10, 0 /* must be > 0 */); });
assert.throws(function() {
// Current max bin boundary (-7) must be positive.
b0.addExponentialBins(16, 4);
});
let b1 = new tr.v.HistogramBinBoundaries(8);
assert.throws(() => b1.addExponentialBins(20, 0 /* must be > 0 */));
assert.throws(() => b1.addExponentialBins(5 /* must be > 8 */, 3));
assert.throws(() => b1.addExponentialBins(8 /* must be > 8 */, 3));
});
test('statisticsScalars', function() {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
let hist = new tr.v.Histogram('', unitlessNumber, boundaries);
hist.addSample(50);
hist.addSample(60);
hist.addSample(70);
hist.addSample('i am not a number');
hist.customizeSummaryOptions({
count: true,
min: true,
max: true,
sum: true,
avg: true,
std: true,
nans: true,
geometricMean: true,
percentile: [0.5, 1]
});
// Test round-tripping summaryOptions.
hist = tr.v.Histogram.fromDict(hist.asDict());
let stats = hist.statisticsScalars;
assert.strictEqual(stats.get('nans').unit,
tr.b.Unit.byName.count_smallerIsBetter);
assert.strictEqual(stats.get('nans').value, 1);
assert.strictEqual(stats.get('count').unit,
tr.b.Unit.byName.count_smallerIsBetter);
assert.strictEqual(stats.get('count').value, 3);
assert.strictEqual(stats.get('min').unit, hist.unit);
assert.strictEqual(stats.get('min').value, 50);
assert.strictEqual(stats.get('max').unit, hist.unit);
assert.strictEqual(stats.get('max').value, 70);
assert.strictEqual(stats.get('sum').unit, hist.unit);
assert.strictEqual(stats.get('sum').value, 180);
assert.strictEqual(stats.get('avg').unit, hist.unit);
assert.strictEqual(stats.get('avg').value, 60);
assert.strictEqual(stats.get('std').value, 10);
assert.strictEqual(stats.get('pct_050').unit, hist.unit);
assert.closeTo(stats.get('pct_050').value, 60, 1);
assert.strictEqual(stats.get('pct_100').unit, hist.unit);
assert.closeTo(stats.get('pct_100').value, 70, 1);
assert.strictEqual(stats.get('geometricMean').unit, hist.unit);
assert.closeTo(stats.get('geometricMean').value, 59.439, 1e-3);
});
test('statisticsScalarsNoSummaryOptions', function() {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
let hist = new tr.v.Histogram('', unitlessNumber, boundaries);
hist.addSample(50);
hist.addSample(60);
hist.addSample(70);
hist.customizeSummaryOptions({
count: false,
min: false,
max: false,
sum: false,
avg: false,
std: false,
percentile: []
});
assert.strictEqual(hist.statisticsScalars.size, 0);
});
test('statisticsScalarsEmptyHistogram', function() {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 100, 100);
let hist = new tr.v.Histogram('', unitlessNumber, boundaries);
hist.customizeSummaryOptions({
count: true,
min: true,
max: true,
sum: true,
avg: true,
std: true,
percentile: [0, 0.01, 0.1, 0.5, 0.995, 1]
});
let stats = hist.statisticsScalars;
assert.strictEqual(stats.get('count').value, 0);
assert.strictEqual(stats.get('min').value, Infinity);
assert.strictEqual(stats.get('max').value, -Infinity);
assert.strictEqual(stats.get('sum').value, 0);
assert.strictEqual(stats.get('avg'), undefined);
assert.strictEqual(stats.get('std'), undefined);
assert.strictEqual(stats.get('pct_000').value, 0);
assert.strictEqual(stats.get('pct_001').value, 0);
assert.strictEqual(stats.get('pct_010').value, 0);
assert.strictEqual(stats.get('pct_050').value, 0);
assert.strictEqual(stats.get('pct_099_5').value, 0);
assert.strictEqual(stats.get('pct_100').value, 0);
});
test('sampleValues', function() {
let boundaries = tr.v.HistogramBinBoundaries.createLinear(0, 1000, 50);
let hist0 = new tr.v.Histogram('', unitlessNumber, boundaries);
let hist1 = new tr.v.Histogram('', unitlessNumber, boundaries);
// maxNumSampleValues defaults to numBins * 10, which, including the
// underflow bin and overflow bin plus this builder's 10 central bins,
// is 52 * 10.
assert.strictEqual(hist0.maxNumSampleValues, 520);
assert.strictEqual(hist1.maxNumSampleValues, 520);
let values0 = [];
let values1 = [];
for (let i = 0; i < 10; ++i) {
values0.push(i);
hist0.addSample(i);
}
for (let i = 10; i < 20; ++i) {
values1.push(i);
hist1.addSample(i);
}
assert.deepEqual(hist0.sampleValues, values0);
assert.deepEqual(hist1.sampleValues, values1);
hist0.addHistogram(hist1);
assert.deepEqual(hist0.sampleValues, values0.concat(values1));
let hist2 = tr.v.Histogram.fromDict(hist0.asDict());
assert.deepEqual(hist2.sampleValues, values0.concat(values1));
for (let i = 0; i < 500; ++i) {
hist0.addSample(i);
}
assert.strictEqual(hist0.sampleValues.length, hist0.maxNumSampleValues);
let hist3 = new tr.v.Histogram('', unitlessNumber, boundaries);
hist3.maxNumSampleValues = 10;
for (let i = 0; i < 100; ++i) {
hist3.addSample(i);
}
assert.strictEqual(hist3.sampleValues.length, 10);
});
test('singularBin', function() {
let hist = new tr.v.Histogram('', unitlessNumber,
tr.v.HistogramBinBoundaries.SINGULAR);
assert.lengthOf(hist.allBins, 1);
let dict = hist.asDict();
assert.isUndefined(dict.binBoundaries);
let clone = tr.v.Histogram.fromDict(dict);
assert.lengthOf(clone.allBins, 1);
assert.deepEqual(dict, clone.asDict());
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(0, hist.getApproximatePercentile(1));
hist.addSample(0);
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(0, hist.getApproximatePercentile(1));
hist.addSample(1);
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(1, hist.getApproximatePercentile(1));
hist.addSample(2);
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(1, hist.getApproximatePercentile(0.5));
assert.strictEqual(2, hist.getApproximatePercentile(1));
hist.addSample(3);
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(1, hist.getApproximatePercentile(0.5));
assert.strictEqual(2, hist.getApproximatePercentile(0.9));
assert.strictEqual(3, hist.getApproximatePercentile(1));
hist.addSample(4);
assert.strictEqual(0, hist.getApproximatePercentile(0));
assert.strictEqual(1, hist.getApproximatePercentile(0.4));
assert.strictEqual(2, hist.getApproximatePercentile(0.7));
assert.strictEqual(3, hist.getApproximatePercentile(0.9));
assert.strictEqual(4, hist.getApproximatePercentile(1));
});
test('mergeSummaryOptions', function() {
let hist0 = new tr.v.Histogram('', unitlessNumber);
let hist1 = new tr.v.Histogram('', unitlessNumber);
hist0.customizeSummaryOptions({sum: false, percentile: [0.9]});
hist1.customizeSummaryOptions({min: false, percentile: [0.95]});
let merged = hist1.clone();
assert.isFalse(merged.summaryOptions.get('min'));
assert.isTrue(merged.summaryOptions.get('sum'));
assert.deepEqual(merged.summaryOptions.get('percentile'), [0.95]);
merged = hist0.clone();
assert.isTrue(merged.summaryOptions.get('min'));
assert.isFalse(merged.summaryOptions.get('sum'));
assert.deepEqual(merged.summaryOptions.get('percentile'), [0.9]);
merged.addHistogram(hist1);
assert.isTrue(merged.summaryOptions.get('min'));
assert.isTrue(merged.summaryOptions.get('sum'));
assert.deepEqual(merged.summaryOptions.get('percentile'), [0.9, 0.95]);
});
});
</script>