Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5732)

Unified Diff: Source/devtools/front_end/timeline/TimelineTreeView.js

Issue 1298543002: DevTools: Support Top-Down tree view on Timeline (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: addressing comments. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/devtools/front_end/timeline/TimelinePanel.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/devtools/front_end/timeline/TimelineTreeView.js
diff --git a/Source/devtools/front_end/timeline/TimelineTreeView.js b/Source/devtools/front_end/timeline/TimelineTreeView.js
index 24fd410b0f750689eb43b26c2500750794f21152..2c68e09c7ee4e58efe6eca5100fc2233aa926817 100644
--- a/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -15,11 +15,17 @@ WebInspector.TimelineTreeView = function(model)
this._model = model;
var columns = [];
columns.push({id: "self", title: WebInspector.UIString("Self Time"), width: "120px", sort: WebInspector.DataGrid.Order.Descending, sortable: true});
- columns.push({id: "total", title: WebInspector.UIString("Total Time"), width: "120px", sort: WebInspector.DataGrid.Order.Descending, sortable: true});
+ columns.push({id: "total", title: WebInspector.UIString("Total Time"), width: "120px", sortable: true});
columns.push({id: "activity", title: WebInspector.UIString("Activity"), disclosure: true, sortable: true});
+ var nonessentialEvents = [
+ WebInspector.TimelineModel.RecordType.EventDispatch,
+ WebInspector.TimelineModel.RecordType.FunctionCall,
+ WebInspector.TimelineModel.RecordType.TimerFire
+ ];
this._filters = [
WebInspector.TimelineUIUtils.hiddenEventsFilter(),
+ new WebInspector.ExclusiveTraceEventNameFilter(nonessentialEvents),
new WebInspector.ExcludeTopLevelFilter()
];
@@ -36,6 +42,14 @@ WebInspector.TimelineTreeView = function(model)
/**
* @enum {string}
*/
+WebInspector.TimelineTreeView.Mode = {
+ TopDown: "TopDown",
+ BottomUp: "BottomUp"
+}
+
+/**
+ * @enum {string}
+ */
WebInspector.TimelineTreeView.GroupBy = {
None: "None",
Domain: "Domain",
@@ -51,138 +65,169 @@ WebInspector.TimelineTreeView.prototype = {
{
this._startTime = selection.startTime();
this._endTime = selection.endTime();
- this._refreshRecords();
+ this._refreshTree();
},
_createToolbar: function()
{
- this._panelToolbar = new WebInspector.Toolbar(this.element);
+ var panelToolbar = new WebInspector.Toolbar(this.element);
+ panelToolbar.appendToolbarItem(new WebInspector.ToolbarText(WebInspector.UIString("View")));
+
+ this._modeCombobox = new WebInspector.ToolbarComboBox(this._onTreeModeChanged.bind(this));
+ this._modeCombobox.addOption(this._modeCombobox.createOption(WebInspector.UIString("Costly Functions"), "", WebInspector.TimelineTreeView.Mode.BottomUp));
+ this._modeCombobox.addOption(this._modeCombobox.createOption(WebInspector.UIString("Costly Entrypoints"), "", WebInspector.TimelineTreeView.Mode.TopDown));
+ panelToolbar.appendToolbarItem(this._modeCombobox);
+
this._groupByCombobox = new WebInspector.ToolbarComboBox(this._onGroupByChanged.bind(this));
/**
* @param {string} name
* @param {string} id
* @this {WebInspector.TimelineTreeView}
*/
- function addOption(name, id)
+ function addGroupingOption(name, id)
{
var option = this._groupByCombobox.createOption(name, "", id);
this._groupByCombobox.addOption(option);
if (id === this._groupBySetting.get())
this._groupByCombobox.select(option);
}
- addOption.call(this, WebInspector.UIString("No Grouping"), WebInspector.TimelineTreeView.GroupBy.None);
- addOption.call(this, WebInspector.UIString("Group by Domain"), WebInspector.TimelineTreeView.GroupBy.Domain);
- addOption.call(this, WebInspector.UIString("Group by Domain (2nd Level)"), WebInspector.TimelineTreeView.GroupBy.DomainSecondLevel);
- addOption.call(this, WebInspector.UIString("Group by URL"), WebInspector.TimelineTreeView.GroupBy.URL);
- this._panelToolbar.appendToolbarItem(this._groupByCombobox);
+ panelToolbar.appendToolbarItem(new WebInspector.ToolbarText(WebInspector.UIString("Group by")));
+ addGroupingOption.call(this, WebInspector.UIString("Function"), WebInspector.TimelineTreeView.GroupBy.None);
+ addGroupingOption.call(this, WebInspector.UIString("Domain"), WebInspector.TimelineTreeView.GroupBy.Domain);
+ addGroupingOption.call(this, WebInspector.UIString("Domain (2nd Level)"), WebInspector.TimelineTreeView.GroupBy.DomainSecondLevel);
+ addGroupingOption.call(this, WebInspector.UIString("URL"), WebInspector.TimelineTreeView.GroupBy.URL);
+ panelToolbar.appendToolbarItem(this._groupByCombobox);
+ },
+
+ _onTreeModeChanged: function()
+ {
+ this._refreshTree();
},
_onGroupByChanged: function()
{
this._groupBySetting.set(this._groupByCombobox.selectedOption().value);
- this._refreshRecords();
+ this._refreshTree();
},
- _refreshRecords: function()
+ _refreshTree: function()
{
- var groupBy = this._groupBySetting.get();
- var groupNodes = new Map();
+ this.dataGrid.rootNode().removeChildren();
+ var topDown = WebInspector.TimelineModel.buildTopDownTree(
+ this._model.mainThreadEvents(), this._startTime, this._endTime, this._filters, WebInspector.TimelineTreeView.eventId);
+ var tree = this._modeCombobox.selectedOption().value === WebInspector.TimelineTreeView.Mode.TopDown
+ ? this._preformTopDownTreeGrouping(topDown)
+ : this._buildBottomUpTree(topDown);
+ for (var child of tree.children.values()) {
+ // Exclude the idle time off the total calculation.
+ var gridNode = new WebInspector.TimelineTreeView.GridNode(child, topDown.totalTime);
+ this.dataGrid.insertChild(gridNode);
+ }
+ this._sortingChanged();
+ },
- /**
- * @param {string} id
- * @return {!WebInspector.TimelineModel.ProfileTreeNode}
- */
- function groupNodeById(id)
- {
- var node = groupNodes.get(id);
- if (!node) {
- node = new WebInspector.TimelineModel.ProfileTreeNode();
- node.name = id || WebInspector.UIString("(unknown)");
- node.selfTime = 0;
- node.totalTime = 0;
- groupNodes.set(id, node);
+ /**
+ * @param {!WebInspector.TimelineModel.ProfileTreeNode} topDownTree
+ * @return {!WebInspector.TimelineModel.ProfileTreeNode}
+ */
+ _preformTopDownTreeGrouping: function(topDownTree)
+ {
+ var nodeToGroupId = this._nodeToGroupIdFunction();
+ if (nodeToGroupId) {
+ this._groupNodes = new Map();
+ for (var node of topDownTree.children.values()) {
+ var groupNode = this._nodeToGroupNode(nodeToGroupId, node);
+ groupNode.selfTime += node.selfTime;
+ groupNode.totalTime += node.totalTime;
+ groupNode.children.set(node.id, node);
}
- return node;
+ topDownTree.children = this._groupNodes;
+ this._groupNodes = null;
}
+ return topDownTree;
+ },
- /**
- * @return {?WebInspector.TimelineModel.ProfileTreeNode}
- */
- function groupByNone()
- {
- return null;
- }
+ /**
+ * @param {!WebInspector.TimelineModel.ProfileTreeNode} topDownTree
+ * @return {!WebInspector.TimelineModel.ProfileTreeNode}
+ */
+ _buildBottomUpTree: function(topDownTree)
+ {
+ this._groupNodes = new Map();
+ var nodeToGroupId = this._nodeToGroupIdFunction();
+ var nodeToGroupNode = nodeToGroupId ? this._nodeToGroupNode.bind(this, nodeToGroupId) : null;
+ var bottomUpRoot = WebInspector.TimelineModel.buildBottomUpTree(topDownTree, nodeToGroupNode);
+ for (var group of this._groupNodes)
+ bottomUpRoot.children.set(group[0], group[1]);
+ return bottomUpRoot;
+ },
+ /**
+ * @return {?function(!WebInspector.TimelineModel.ProfileTreeNode):string}
+ */
+ _nodeToGroupIdFunction: function()
+ {
/**
* @param {!WebInspector.TimelineModel.ProfileTreeNode} node
- * @return {?WebInspector.TimelineModel.ProfileTreeNode}
+ * @return {string}
*/
function groupByURL(node)
{
- return groupNodeById(WebInspector.TimelineTreeView.eventURL(node.event) || "");
+ return WebInspector.TimelineTreeView.eventURL(node.event) || "";
}
/**
* @param {!WebInspector.TimelineModel.ProfileTreeNode} node
- * @return {?WebInspector.TimelineModel.ProfileTreeNode}
+ * @return {string}
*/
function groupByDomain(node)
{
var parsedURL = (WebInspector.TimelineTreeView.eventURL(node.event) || "").asParsedURL();
- var domain = parsedURL && parsedURL.host || "";
- return groupNodeById(domain);
+ return parsedURL && parsedURL.host || "";
}
/**
* @param {!WebInspector.TimelineModel.ProfileTreeNode} node
- * @return {?WebInspector.TimelineModel.ProfileTreeNode}
+ * @return {string}
*/
function groupByDomainSecondLevel(node)
{
var parsedURL = (WebInspector.TimelineTreeView.eventURL(node.event) || "").asParsedURL();
if (!parsedURL)
- return groupNodeById("");
+ return "";
if (/^[.0-9]+$/.test(parsedURL.host))
- return groupNodeById(parsedURL.host)
+ return parsedURL.host;
var domainMatch = /([^.]*\.)?[^.]*$/.exec(parsedURL.host);
- return groupNodeById(domainMatch && domainMatch[0] || "");
+ return domainMatch && domainMatch[0] || "";
}
- /**
- * @param {!WebInspector.TracingModel.Event} e
- * @return {string}
- */
- function eventId(e)
- {
- // Function call frames are always groupped by the URL
- if (e.name === "JSFrame") {
- var data = e.args["data"];
- return "f:" + (data["callUID"] || WebInspector.TimelineTreeView.eventURL(e));
- }
- // While the rest of events are groupped by the event type
- // unless the group by URL/Domain mode is on.
- if (groupBy === WebInspector.TimelineTreeView.GroupBy.URL)
- return e.name + ":@" + WebInspector.TimelineTreeView.eventURL(e);
- return e.name;
- }
-
- var groupByMapper = new Map([
- [WebInspector.TimelineTreeView.GroupBy.None, groupByNone],
+ var groupByMap = /** @type {!Map<!WebInspector.TimelineTreeView.GroupBy,?function(!WebInspector.TimelineModel.ProfileTreeNode):string>} */ (new Map([
+ [WebInspector.TimelineTreeView.GroupBy.None, null],
[WebInspector.TimelineTreeView.GroupBy.Domain, groupByDomain],
[WebInspector.TimelineTreeView.GroupBy.DomainSecondLevel, groupByDomainSecondLevel],
[WebInspector.TimelineTreeView.GroupBy.URL, groupByURL]
- ]);
- var topDown = WebInspector.TimelineModel.buildTopDownTree(this._model.mainThreadEvents(), this._startTime, this._endTime, this._filters, eventId);
- var bottomUpRoot = WebInspector.TimelineModel.buildBottomUpTree(topDown, groupByMapper.get(groupBy));
- for (var group of groupNodes)
- bottomUpRoot.children.set(group[0], group[1]);
- this.dataGrid.rootNode().removeChildren();
- for (var child of bottomUpRoot.children.values()) {
- // Exclude the idle time off the total calculation.
- var gridNode = new WebInspector.TimelineTreeView.GridNode(child, topDown.totalTime);
- this.dataGrid.insertChild(gridNode);
+ ]));
+ return groupByMap.get(this._groupBySetting.get()) || null;
+ },
+
+ /**
+ * @param {function(!WebInspector.TimelineModel.ProfileTreeNode):string} nodeToGroupId
+ * @param {!WebInspector.TimelineModel.ProfileTreeNode} node
+ * @return {!WebInspector.TimelineModel.ProfileTreeNode}
+ */
+ _nodeToGroupNode: function(nodeToGroupId, node)
+ {
+ var id = nodeToGroupId(node);
+ var groupNode = this._groupNodes.get(id);
+ if (!groupNode) {
+ groupNode = new WebInspector.TimelineModel.ProfileTreeNode();
+ groupNode.name = id || WebInspector.UIString("(unattributed)");
+ groupNode.selfTime = 0;
+ groupNode.totalTime = 0;
+ groupNode.children = new Map();
+ this._groupNodes.set(id, groupNode);
}
- this._sortingChanged();
+ return groupNode;
},
_sortingChanged: function()
@@ -215,6 +260,19 @@ WebInspector.TimelineTreeView.prototype = {
/**
* @param {!WebInspector.TracingModel.Event} event
+ * @return {string}
+ */
+WebInspector.TimelineTreeView.eventId = function(event)
+{
+ if (event.name === WebInspector.TimelineModel.RecordType.JSFrame) {
+ var data = event.args["data"];
+ return "f:" + (data["callUID"] || WebInspector.TimelineTreeView.eventURL(event));
+ }
+ return event.name + ":@" + WebInspector.TimelineTreeView.eventURL(event);
+}
+
+/**
+ * @param {!WebInspector.TracingModel.Event} event
* @return {?string}
*/
WebInspector.TimelineTreeView.eventURL = function(event)
« no previous file with comments | « Source/devtools/front_end/timeline/TimelinePanel.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698