blob: d6604a6aed9757ba7310381602450a0d10a35a65 [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/extras/chrome/chrome_user_friendly_category_driver.html">
<link rel="import" href="/tracing/metrics/metric_registry.html">
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.exportTo('tr.metrics.sh', function() {
var LONG_TASK_MS = 50;
// Anything longer than this should be so rare that its length beyond this is
// uninteresting.
var LONGEST_TASK_MS = 1000;
/**
* This helper function calls |cb| for each of the top-level tasks on the
* given thread in the given range whose duration is longer than LONG_TASK_MS.
*
* @param {tr.model.Thread} thread
* @param {tr.b.Range=} opt_range
* @param {function()} cb
* @param {Object=} opt_this
*/
function iterateLongTopLevelTasksOnThreadInRange(
thread, opt_range, cb, opt_this) {
thread.sliceGroup.topLevelSlices.forEach(function(slice) {
if (opt_range &&
!opt_range.intersectsExplicitRangeInclusive(slice.start, slice.end))
return;
if (slice.duration < LONG_TASK_MS)
return;
cb.call(opt_this, slice);
});
}
/**
* This helper function calls |cb| for each of the main renderer threads in
* the model.
*
* @param {tr.model.Model} model The model.
* @param {function()} cb Callback.
* @param {Object=} opt_this Context object.
*/
function iterateRendererMainThreads(model, cb, opt_this) {
var modelHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
tr.b.dictionaryValues(modelHelper.rendererHelpers).forEach(
function(rendererHelper) {
if (!rendererHelper.mainThread)
return;
cb.call(opt_this, rendererHelper.mainThread);
});
}
/**
* This metric directly measures long tasks on renderer main threads.
* This metric requires only the 'toplevel' tracing category.
*
* @param {!tr.v.ValueSet} values
* @param {!tr.model.Model} model
* @param {!Object=} opt_options
*/
function longTasksMetric(values, model, opt_options) {
var rangeOfInterest = opt_options ? opt_options.rangeOfInterest : undefined;
var longTaskNumeric = new tr.v.Histogram('long tasks',
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,
tr.v.HistogramBinBoundaries.createLinear(
LONG_TASK_MS, LONGEST_TASK_MS, 40));
longTaskNumeric.description = 'durations of long tasks';
var slices = new tr.model.EventSet();
iterateRendererMainThreads(model, function(thread) {
iterateLongTopLevelTasksOnThreadInRange(
thread, rangeOfInterest, function(task) {
longTaskNumeric.addSample(task.duration,
{relatedEvents: new tr.v.d.RelatedEventSet([task])});
slices.push(task);
slices.addEventSet(task.descendentSlices);
});
});
values.addHistogram(longTaskNumeric);
var sampleForEvent = undefined;
var composition = tr.v.d.Composition.buildFromEvents(
values, 'long tasks ', slices,
e => (model.getUserFriendlyCategoryFromEvent(e) || 'unknown'),
tr.b.Unit.byName.timeDurationInMs_smallerIsBetter, sampleForEvent,
tr.v.HistogramBinBoundaries.createExponential(1, LONGEST_TASK_MS, 40));
composition.colorScheme =
tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;
longTaskValue.diagnostics.set('category', composition);
}
tr.metrics.MetricRegistry.register(longTasksMetric, {
supportsRangeOfInterest: true
});
return {
longTasksMetric: longTasksMetric,
iterateLongTopLevelTasksOnThreadInRange:
iterateLongTopLevelTasksOnThreadInRange,
iterateRendererMainThreads: iterateRendererMainThreads,
LONG_TASK_MS: LONG_TASK_MS,
LONGEST_TASK_MS: LONGEST_TASK_MS
};
});
</script>