blob: 357251fa8752b5fd86ab94e3e6d4f8a77332700f [file] [log] [blame]
<!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/base/math/range.html">
<link rel="import" href="/tracing/metrics/metric_registry.html">
<link rel="import" href="/tracing/metrics/spa_navigation_helper.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.exportTo('tr.metrics', function() {
const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY =
tr.v.HistogramBinBoundaries.createExponential(1, 1000, 50);
/**
* This metric measures the duration between the input event
* causing a SPA navigation and the first paint event after it.
*/
function spaNavigationMetric(histograms, model) {
let histogram = new tr.v.Histogram(
'spaNavigationStartToFpDuration',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);
histogram.description = 'Latency between the input event causing' +
' a SPA navigation and the first paint event after it';
histogram.customizeSummaryOptions({
count: false,
sum: false,
});
let modelHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
if (!modelHelper) {
// Chrome isn't present.
return;
}
let rendererHelpers = modelHelper.rendererHelpers;
if (!rendererHelpers) {
// We couldn't find any renderer processes.
return;
}
let browserHelper = modelHelper.browserHelper;
for (let rendererHelper of Object.values(rendererHelpers)) {
let spaNavigations = tr.metrics.findSpaNavigationsOnRenderer(
rendererHelper, browserHelper);
for (let spaNav of spaNavigations) {
let beginData = spaNav.navigationStart.args.data;
// TODO(sunjian): rename convertTimestampToModelTime to something like
// convertTraceEventTsToModelTs and get rid of the first parameter.
let beginTs = model.convertTimestampToModelTime(
'traceEventClock',
beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);
let duration = spaNav.firstPaintEvent.start - beginTs;
let breakdownDict = rendererHelper.generateWallClockTimeBreakdownTree(
beginTs, spaNav.firstPaintEvent.start);
let breakdownDiagnostic = new tr.v.d.Breakdown();
breakdownDiagnostic.colorScheme =
tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
for (let label in breakdownDict) {
breakdownDiagnostic.set(label,
parseInt(breakdownDict[label].total * 1e3) / 1e3);
}
histogram.addSample(
duration,
{
'Breakdown of [navStart, firstPaint]': breakdownDiagnostic,
'Start': new tr.v.d.RelatedEventSet(spaNav.navigationStart),
'End': new tr.v.d.RelatedEventSet(spaNav.firstPaintEvent),
'Navigation infos': new tr.v.d.Generic({
url: spaNav.url,
pid: rendererHelper.pid,
navStart: beginTs,
firstPaint: spaNav.firstPaintEvent.start
})
});
}
}
histograms.addHistogram(histogram);
}
tr.metrics.MetricRegistry.register(spaNavigationMetric);
return {
spaNavigationMetric,
};
});
</script>