blob: 924527f126b9e2b6c5371368de2ad93964a261b4 [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/core/test_utils.html">
<link rel="import" href="/tracing/extras/importer/trace_event_importer.html">
<link rel="import" href="/tracing/metrics/blink/gc_metric.html">
<link rel="import" href="/tracing/metrics/v8/utils.html">
<link rel="import" href="/tracing/model/slice_group.html">
<link rel="import" href="/tracing/value/histogram_set.html">
<script>
'use strict';
tr.b.unittest.testSuite(function() {
function createModel(start, end, slices) {
const opts = {
customizeModelCallback(model) {
const process = model.getOrCreateProcess(1);
const thread = process.getOrCreateThread(2);
const group = thread.sliceGroup;
slices.forEach(function(slice) {
group.pushSlice(tr.c.TestUtils.newSliceEx(slice));
});
group.createSubSlices();
}
};
const model = tr.c.TestUtils.newModelWithEvents([], opts);
return model;
}
function constructName(name, suffix) {
return name + '_' + suffix;
}
function run(slices) {
const histograms = new tr.v.HistogramSet();
const startTime = slices.reduce(
(acc, slice) => (Math.min(acc, slice.start)));
const endTime = slices.reduce((acc, slice) => (Math.max(acc, slice.end)));
const model = createModel(startTime - 1, endTime + 1, slices);
tr.metrics.blink.blinkGcMetric(histograms, model);
return histograms;
}
test('topEvents', function() {
const events = {
'BlinkGC.AtomicPhase': 'blink-gc-atomic-phase',
'BlinkGC.CompleteSweep': 'blink-gc-complete-sweep',
'BlinkGC.LazySweepInIdle': 'blink-gc-lazy-sweep-idle'
};
for (const [timelineName, telemetryName] of Object.entries(events)) {
const slices = [
{
title: timelineName, args: {}, start: 100, end: 200,
cpuStart: 100, cpuEnd: 200
}
];
const actual = run(slices);
let value = actual.getHistogramNamed(telemetryName);
assert.strictEqual(value.running.sum, 100);
assert.strictEqual(value.numValues, 1);
assert.strictEqual(value.average, 100);
assert.strictEqual(value.running.max, 100);
assert.closeTo(value.getApproximatePercentile(0.90), 100, 1);
value = actual.getHistogramNamed(
`${telemetryName}_idle_deadline_overrun`);
assert.strictEqual(value.running.sum, 0);
assert.strictEqual(value.numValues, 1);
assert.strictEqual(value.average, 0);
assert.strictEqual(value.running.max, 0);
value = actual.getHistogramNamed(`${telemetryName}_outside_idle`);
assert.strictEqual(value.running.sum, 100);
assert.strictEqual(value.numValues, 1);
assert.strictEqual(value.average, 100);
value = actual.getHistogramNamed(`${telemetryName}_percentage_idle`);
assert.strictEqual(value.average, 0);
}
});
test('idleTimes', function() {
const histograms = new tr.v.HistogramSet();
const slices = [
{
title: 'SingleThreadIdleTaskRunner::RunTask',
args: {'allotted_time_ms': 100}, start: 100, end: 200,
cpuStart: 100, cpuEnd: 200
},
{
title: 'BlinkGC.AtomicPhase', args: {}, start: 110, end: 190,
cpuStart: 110, cpuEnd: 190
}
];
const actual = run(slices);
let value = actual.getHistogramNamed('blink-gc-atomic-phase');
assert.strictEqual(value.running.sum, 80);
assert.strictEqual(value.numValues, 1);
assert.strictEqual(value.average, 80);
assert.strictEqual(value.running.max, 80);
value = actual.getHistogramNamed(
'blink-gc-atomic-phase_idle_deadline_overrun');
assert.strictEqual(value.running.sum, 0);
assert.strictEqual(value.average, 0);
assert.strictEqual(value.running.max, 0);
value = actual.getHistogramNamed('blink-gc-atomic-phase_outside_idle');
assert.strictEqual(value.running.sum, 0);
assert.strictEqual(value.average, 0);
assert.strictEqual(value.running.max, 0);
value = actual.getHistogramNamed('blink-gc-atomic-phase_percentage_idle');
assert.strictEqual(value.average, 1);
});
test('idleTimeOverrun', function() {
const histograms = new tr.v.HistogramSet();
const slices = [
{
title: 'SingleThreadIdleTaskRunner::RunTask',
args: {'allotted_time_ms': 10}, start: 100, end: 200,
cpuStart: 100, cpuEnd: 200
},
{
title: 'BlinkGC.AtomicPhase', args: {}, start: 110, end: 190,
cpuStart: 110, cpuEnd: 190
}
];
const actual = run(slices);
let value = actual.getHistogramNamed('blink-gc-atomic-phase');
assert.strictEqual(value.running.sum, 80);
assert.strictEqual(value.numValues, 1);
assert.strictEqual(value.average, 80);
assert.strictEqual(value.running.max, 80);
value = actual.getHistogramNamed(
'blink-gc-atomic-phase_idle_deadline_overrun');
assert.strictEqual(value.running.sum, 70);
assert.strictEqual(value.average, 70);
assert.strictEqual(value.running.max, 70);
value = actual.getHistogramNamed('blink-gc-atomic-phase_outside_idle');
assert.strictEqual(value.running.sum, 70);
assert.strictEqual(value.average, 70);
assert.strictEqual(value.running.max, 70);
value = actual.getHistogramNamed('blink-gc-atomic-phase_percentage_idle');
assert.closeTo(value.average, 1 / 8, 1e-6);
});
test('totalTimeForBlinkGC', function() {
const histograms = new tr.v.HistogramSet();
const slices = [
{
title: 'BlinkGC.AtomicPhase', args: {}, start: 100, end: 200,
cpuStart: 100, cpuEnd: 200
},
{
title: 'BlinkGC.LazySweepInIdle', args: {}, start: 210,
end: 290, cpuStart: 210, cpuEnd: 290
}
];
const actual = run(slices);
let value = actual.getHistogramNamed('blink-gc-total');
assert.strictEqual(value.running.sum, 180);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 90);
assert.strictEqual(value.running.max, 100);
value = actual.getHistogramNamed('blink-gc-total_idle_deadline_overrun');
assert.strictEqual(value.running.sum, 0);
assert.strictEqual(value.average, 0);
assert.strictEqual(value.running.max, 0);
value = actual.getHistogramNamed('blink-gc-total_outside_idle');
assert.strictEqual(value.running.sum, 180);
assert.strictEqual(value.average, 90);
assert.strictEqual(value.running.max, 100);
value = actual.getHistogramNamed('blink-gc-total_percentage_idle');
assert.strictEqual(value.average, 0);
});
test('totalTimeForUnifiedGC', function() {
const histograms = new tr.v.HistogramSet();
const slices = [
{
title: 'V8.GCFinalizeMC', args: {},
start: 100, end: 300, cpuStart: 100, cpuEnd: 300
},
{
title: 'BlinkGC.AtomicPhase', args: {},
start: 310, end: 410, cpuStart: 310, cpuEnd: 410
}
];
const actual = run(slices);
const value = actual.getHistogramNamed('unified-gc-total');
assert.strictEqual(value.running.sum, 300);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 150);
assert.strictEqual(value.running.max, 200);
});
test('totalTimeForUnifiedGCBlinkNestedInV8', function() {
// Nested Blink GC in V8 top-level GC can happen during unified garbage
// collection, or when callbacks that trigger e.g. sweeping are fired
// from V8's GC. These should only be accounted once.
const histograms = new tr.v.HistogramSet();
const slices = [
{
title: 'V8.GCFinalizeMC', args: {},
start: 100, end: 300, cpuStart: 100, cpuEnd: 300
},
// Nested events should be ignored.
{
title: 'BlinkGC.CompleteSweep', args: {},
start: 200, end: 270, cpuStart: 200, cpuEnd: 270
},
{
title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
start: 280, end: 290, cpuStart: 280, cpuEnd: 290
},
// Next event is outside of nesting and should be accounted for.
{
title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
start: 310, end: 320, cpuStart: 310, cpuEnd: 320
},
];
const actual = run(slices);
const value = actual.getHistogramNamed('unified-gc-total');
assert.strictEqual(value.running.sum, 210);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 105);
assert.strictEqual(value.running.max, 200);
});
function getSlicesWithForcedV8GCs() {
return [
{
title: tr.metrics.v8.utils.forcedGCEventName(), args: {},
start: 100, end: 300, cpuStart: 100, cpuEnd: 300
},
// Following nested events should be ignored.
{
title: 'V8.GCFinalizeMC', args: {},
start: 100, end: 300, cpuStart: 100, cpuEnd: 300
},
{
title: 'BlinkGC.CompleteSweep', args: {},
start: 200, end: 270, cpuStart: 200, cpuEnd: 270
},
{
title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
start: 280, end: 290, cpuStart: 280, cpuEnd: 290
},
// Next event happens after the forced GC and should be accounted for.
{
title: 'BlinkGC.IncrementalMarkingStartMarking', args: {},
start: 310, end: 320, cpuStart: 310, cpuEnd: 320
},
{
title: 'BlinkGC.AtomicPhase', args: {'forced': false},
start: 320, end: 330, cpuStart: 320, cpuEnd: 330
},
];
}
test('ignoreForcedV8GCEventsForUnifiedMetric', function() {
// Any events nested in a forced GC should be ignored.
const histograms = new tr.v.HistogramSet();
const actual = run(getSlicesWithForcedV8GCs());
const value = actual.getHistogramNamed('unified-gc-total');
assert.strictEqual(value.running.sum, 20);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 10);
assert.strictEqual(value.running.max, 10);
});
test('ignoreForcedV8GCEventsForBlinkMetric', function() {
// Any events nested in a forced GC should be ignored.
const histograms = new tr.v.HistogramSet();
const actual = run(getSlicesWithForcedV8GCs());
const value = actual.getHistogramNamed('blink-gc-total');
assert.strictEqual(value.running.sum, 20);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 10);
assert.strictEqual(value.running.max, 10);
});
function getSlicesWithForcedBlinkGCs() {
return [
// Following nested events should be ignored.
{
title: 'BlinkGC.CompleteSweep', args: {'forced': true},
start: 200, end: 270, cpuStart: 200, cpuEnd: 270
},
{
title: 'BlinkGC.AtomicPhase', args: {'forced': true},
start: 280, end: 290, cpuStart: 280, cpuEnd: 290
},
// Next events are not forced and should be accounted for.
{
title: 'BlinkGC.AtomicPhase', args: {},
start: 310, end: 320, cpuStart: 310, cpuEnd: 320
},
{
title: 'BlinkGC.AtomicPhase', args: {'forced': false},
start: 320, end: 330, cpuStart: 320, cpuEnd: 330
},
];
}
test('ignoreForcedBlinkGCEventsForUnifiedMetric', function() {
// Any forced Blink GC events should be ignored.
const histograms = new tr.v.HistogramSet();
const actual = run(getSlicesWithForcedBlinkGCs());
const value = actual.getHistogramNamed('unified-gc-total');
assert.strictEqual(value.running.sum, 20);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 10);
assert.strictEqual(value.running.max, 10);
});
test('ignoreForcedBlinkGCEventsForBlinkMetric', function() {
// Any forced Blink GC events should be ignored.
const histograms = new tr.v.HistogramSet();
const actual = run(getSlicesWithForcedBlinkGCs());
const value = actual.getHistogramNamed('blink-gc-total');
assert.strictEqual(value.running.sum, 20);
assert.strictEqual(value.numValues, 2);
assert.strictEqual(value.average, 10);
assert.strictEqual(value.running.max, 10);
});
});
</script>