blob: 50ff3867d93a0ecb74f9bb5711776451638d746a [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2015 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="/perf_insights/mre/function_handle.html">
<link rel="import" href="/tracing/base/math/range.html">
<link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
<script>
'use strict';
tr.exportTo('pie', function() {
// Collects the set of tasks that are preventing user input from being
// processed on the main thread.
// See https://goo.gl/l7V5xg.
function mapInputBlockers(result, model) {
var modelHelper = model.getOrCreateHelper(
tr.model.helpers.ChromeModelHelper);
var rendererHelpers = modelHelper.rendererHelpers;
if (!rendererHelpers) {
// If we didn't detect any renderer processes, bail out.
result.addPair('inputBlockers', null);
return;
}
// Look for main thread input handling in each renderer process.
var inputBlockers = {};
var foundInputBlockers = false;
for (var pid in rendererHelpers) {
var rendererHelper = rendererHelpers[pid];
var mainThread = rendererHelper.mainThread;
// Look for events that represent main thread input handling that also
// have one associated flow event showing where the input came from.
for (var event of mainThread.getDescendantEvents()) {
if (event.title !== 'LatencyInfo.Flow' ||
event.args['step'] !== 'HandleInputEventMain' ||
event.inFlowEvents.length !== 1) {
continue;
}
// Now we can derive the queueing interval from the flow event.
var flowEvent = event.inFlowEvents[0];
var queueRange =
tr.b.math.Range.fromExplicitRange(flowEvent.start, event.start);
// Find all events that intersect the queueing interval and compute how
// much they contributed to it.
for (var intersectingEvent of mainThread.getDescendantEvents()) {
var eventRange =
tr.b.math.Range.fromExplicitRange(intersectingEvent.start,
intersectingEvent.start + intersectingEvent.duration);
var intersection = queueRange.findIntersection(eventRange);
if (intersection.isEmpty || intersection.duration === 0)
continue;
if (inputBlockers[intersectingEvent.title] === undefined)
inputBlockers[intersectingEvent.title] = [];
inputBlockers[intersectingEvent.title].push(intersection.duration);
foundInputBlockers = true;
}
}
}
if (!foundInputBlockers) {
result.addPair('inputBlockers', null);
return;
}
result.addPair('inputBlockers', inputBlockers);
}
pi.FunctionRegistry.register(mapInputBlockers);
return {
mapInputBlockersForTest: mapInputBlockers
};
});
</script>