Commit 85f612d2 authored by Alexei Filippov's avatar Alexei Filippov Committed by Commit Bot

DevTools: Add aggregated tree for user timing events on timeline.

BUG=826045

Change-Id: I7273015bcac131f028116380e928f6a9c6d67182
Reviewed-on: https://chromium-review.googlesource.com/981444
Commit-Queue: Alexei Filippov <alph@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546226}
parent f24e6b29
Test timeline aggregated details.
CallTree
Number of options >= 2: true
Option #2 title: User Timing
HTML done parsing: 0.250 1.000
eval scripts: 0.750 0.750
BottomUp
Number of options >= 2: true
Option #2 title: User Timing
eval scripts: 0.750 0.750
HTML done parsing: 0.750 0.750
HTML done parsing: 0.250 1.000
EventLog
Number of options >= 2: true
Option #2 title: User Timing
HTML done parsing: 0.250 1.000
eval scripts: 0.750 0.750
// Copyright 2018 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.
(async function() {
TestRunner.addResult(`Test timeline aggregated details.\n`);
await TestRunner.loadModule('performance_test_runner');
await TestRunner.loadModule('network_test_runner');
await TestRunner.showPanel('timeline');
const sessionId = '6.23';
const rawTraceEvents = [
{
'args': {'name': 'Renderer'},
'cat': '__metadata',
'name': 'process_name',
'ph': 'M',
'pid': 17851,
'tid': 23,
'ts': 0
},
{
'args': {'name': 'CrRendererMain'},
'cat': '__metadata',
'name': 'thread_name',
'ph': 'M',
'pid': 17851,
'tid': 23,
'ts': 0
},
{
'args': {
'data': {
'page': '0x2f7b63884000',
'sessionId': sessionId,
'persistentIds': true,
'frames': [
{'frame': '0x2f7b63884000', 'url': 'top-page-url', 'name': 'top-page-name'}
]
}
},
'cat': 'disabled-by-default-devtools.timeline',
'name': 'TracingStartedInPage',
'ph': 'I',
'pid': 17851,
'tid': 23,
'ts': 100000,
'tts': 606543
},
{'pid':17851,'tid':23,'ts':101000,'ph':'b','cat':'blink.user_timing','name':'HTML done parsing','args':{},'id':'0x472bc7'},
{'pid':17851,'tid':23,'ts':102000,'ph':'e','cat':'blink.user_timing','name':'HTML done parsing','args':{},'id':'0x472bc7'},
{'pid':17851,'tid':23,'ts':101250,'ph':'b','cat':'blink.user_timing','name':'eval scripts','args':{},'id':'0xa09f70'},
{'pid':17851,'tid':23,'ts':102000,'ph':'e','cat':'blink.user_timing','name':'eval scripts','args':{},'id':'0xa09f70'}
];
const timeline = UI.panels.timeline;
timeline._setModel(PerformanceTestRunner.createPerformanceModelWithEvents(rawTraceEvents));
timeline.requestWindowTimes(0, Infinity);
testEventTree('CallTree');
testEventTree('BottomUp');
testEventTree('EventLog');
TestRunner.completeTest();
function getTreeView(type) {
timeline._flameChart._detailsView._tabbedPane.selectTab(type, true);
return timeline._flameChart._detailsView._tabbedPane.visibleView;
}
function testEventTree(type) {
TestRunner.addResult('');
TestRunner.addResult(type);
const tree = getTreeView(type);
const options = tree._threadSelector.options();
TestRunner.addResult('Number of options >= 2: ' + (options.length >= 2));
TestRunner.addResult('Option #2 title: ' + options[1].title);
tree._currentThreadSetting.set('1');
const rootNode = tree._dataGrid.rootNode();
for (const node of rootNode.children)
printEventTree(1, node._profileNode, node._treeView);
}
function printEventTree(padding, node, treeView) {
let name;
if (node.isGroupNode()) {
name = treeView._displayInfoForGroupNode(node).name;
} else {
name = node.event.name === TimelineModel.TimelineModel.RecordType.JSFrame ?
UI.beautifyFunctionName(node.event.args['data']['functionName']) :
Timeline.TimelineUIUtils.eventTitle(node.event);
}
TestRunner.addResult(' '.repeat(padding) + `${name}: ${node.selfTime.toFixed(3)} ${node.totalTime.toFixed(3)}`);
node.children().forEach(printEventTree.bind(null, padding + 1));
}
})();
......@@ -40,7 +40,7 @@ Timeline.TimelineTreeView = class extends UI.VBox {
*/
setModel(model) {
this._model = model;
this._populateThreadSelector();
this._updateThreadsData();
this.refreshTree();
}
......@@ -155,15 +155,25 @@ Timeline.TimelineTreeView = class extends UI.VBox {
_modelEvents() {
if (!this._model || this._threadSelector.size() === 0)
return [];
return this._threadEvents[Number(this._threadSelector.selectedOption().value)];
return this._threadEvents[Number(this._currentThreadSetting.get())];
}
_populateThreadSelector() {
_updateThreadsData() {
if (!this._model)
return;
const options = [];
const options = [{value: '0', label: ls`Main`, title: ls`Main`}];
this._threadEvents = [this._model.timelineModel().mainThreadEvents()];
options.push({value: '0', label: ls`Main`, title: ls`Main`});
const userTimingGroup = TimelineModel.TimelineModel.AsyncEventGroup.userTiming;
const mainThreadAsyncEvents = this._model.timelineModel().mainThreadAsyncEvents();
const userTimingEvents =
TimelineModel.TimelineModel.buildNestableSyncEventsFromAsync(mainThreadAsyncEvents.get(userTimingGroup) || []);
if (userTimingEvents.length) {
const userTimingTitle = Timeline.TimelineUIUtils.titleForAsyncEventGroup(userTimingGroup);
options.push({value: '1', label: userTimingTitle, title: userTimingTitle});
this._threadEvents.push(userTimingEvents);
}
for (const thread of this._model.timelineModel().virtualThreads()) {
if (!thread.name)
continue;
......
......@@ -1078,6 +1078,30 @@ TimelineModel.TimelineModel = class {
}
return zeroStartRequestsList.concat(requestsList);
}
/**
* @param {!Array<!SDK.TracingModel.Event>} asyncEvents
* @return {!Array<!SDK.TracingModel.Event>}
*/
static buildNestableSyncEventsFromAsync(asyncEvents) {
const stack = [];
const events = [];
for (const event of asyncEvents) {
const startTime = event.startTime;
const endTime = event.endTime;
while (stack.length && startTime >= stack.peekLast().endTime)
stack.pop();
if (stack.length && endTime > stack.peekLast().endTime)
return []; // Events are not properly nested. Bail out.
const syncEvent = new SDK.TracingModel.Event(
event.categoriesString, event.name, SDK.TracingModel.Phase.Complete, startTime, event.thread);
syncEvent.setEndTime(endTime);
syncEvent.addArgs(event.args);
events.push(syncEvent);
stack.push(syncEvent);
}
return events;
}
};
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment