Bug 1132755 - Allocations tree has a bunch of columns that don't make sense, r=jsantell

This commit is contained in:
Victor Porof 2015-03-12 15:05:02 -04:00
parent a86c311078
commit de9ce6e33a
10 changed files with 218 additions and 84 deletions

View File

@ -197,34 +197,14 @@
<vbox id="memory-calltree-view" flex="1"> <vbox id="memory-calltree-view" flex="1">
<hbox class="call-tree-headers-container"> <hbox class="call-tree-headers-container">
<label class="plain call-tree-header"
type="duration"
crop="end"
value="&profilerUI.table.totalDuration2;"/>
<label class="plain call-tree-header"
type="percentage"
crop="end"
value="&profilerUI.table.totalPercentage;"/>
<label class="plain call-tree-header" <label class="plain call-tree-header"
type="allocations" type="allocations"
crop="end" crop="end"
value="&profilerUI.table.totalAlloc;"/> value="&profilerUI.table.totalAlloc;"/>
<label class="plain call-tree-header"
type="self-duration"
crop="end"
value="&profilerUI.table.selfDuration2;"/>
<label class="plain call-tree-header"
type="self-percentage"
crop="end"
value="&profilerUI.table.selfPercentage;"/>
<label class="plain call-tree-header" <label class="plain call-tree-header"
type="self-allocations" type="self-allocations"
crop="end" crop="end"
value="&profilerUI.table.selfAlloc;"/> value="&profilerUI.table.selfAlloc;"/>
<label class="plain call-tree-header"
type="samples"
crop="end"
value="&profilerUI.table.samples;"/>
<label class="plain call-tree-header" <label class="plain call-tree-header"
type="function" type="function"
crop="end" crop="end"

View File

@ -16,6 +16,8 @@ support-files =
[browser_perf-compatibility-04.js] [browser_perf-compatibility-04.js]
[browser_perf-clear-01.js] [browser_perf-clear-01.js]
[browser_perf-clear-02.js] [browser_perf-clear-02.js]
[browser_perf-columns-js-calltree.js]
[browser_perf-columns-memory-calltree.js]
[browser_perf-data-massaging-01.js] [browser_perf-data-massaging-01.js]
[browser_perf-data-samples.js] [browser_perf-data-samples.js]
[browser_perf-details-calltree-render.js] [browser_perf-details-calltree-render.js]

View File

@ -0,0 +1,53 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the js call tree view renders the correct columns.
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, $, $$, DetailsView, JsCallTreeView } = panel.panelWin;
// Enable platform data to show the `busyWait` function in the tree.
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, true);
yield DetailsView.selectView("js-calltree");
ok(DetailsView.isViewSelected(JsCallTreeView), "The call tree is now selected.");
yield startRecording(panel);
yield busyWait(1000);
let rendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
yield stopRecording(panel);
yield rendered;
testCells($, $$, {
"duration": true,
"percentage": true,
"allocations": false,
"self-duration": true,
"self-percentage": true,
"self-allocations": false,
"samples": true,
"function": true
});
yield teardown(panel);
finish();
}
function testCells($, $$, visibleCells) {
for (let cell in visibleCells) {
if (visibleCells[cell]) {
ok($(`.call-tree-cell[type=${cell}]`),
`At least one ${cell} column was visible in the tree.`);
} else {
ok(!$(`.call-tree-cell[type=${cell}]`),
`No ${cell} columns were visible in the tree.`);
}
}
is($$(".call-tree-cell", $(".call-tree-item")).length,
Object.keys(visibleCells).filter(e => visibleCells[e]).length,
"The correct number of cells were found in the tree.");
}

View File

@ -0,0 +1,53 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the memory call tree view renders the correct columns.
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, $, $$, DetailsView, MemoryCallTreeView } = panel.panelWin;
// Enable memory to test.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield DetailsView.selectView("memory-calltree");
ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected.");
yield startRecording(panel);
yield busyWait(1000);
let rendered = once(MemoryCallTreeView, EVENTS.MEMORY_CALL_TREE_RENDERED);
yield stopRecording(panel);
yield rendered;
testCells($, $$, {
"duration": false,
"percentage": false,
"allocations": true,
"self-duration": false,
"self-percentage": false,
"self-allocations": true,
"samples": false,
"function": true
});
yield teardown(panel);
finish();
}
function testCells($, $$, visibleCells) {
for (let cell in visibleCells) {
if (visibleCells[cell]) {
ok($(`.call-tree-cell[type=${cell}]`),
`At least one ${cell} column was visible in the tree.`);
} else {
ok(!$(`.call-tree-cell[type=${cell}]`),
`No ${cell} columns were visible in the tree.`);
}
}
is($$(".call-tree-cell", $(".call-tree-item")).length,
Object.keys(visibleCells).filter(e => visibleCells[e]).length,
"The correct number of cells were found in the tree.");
}

View File

@ -103,9 +103,6 @@ let JsCallTreeView = Heritage.extend(DetailsSubview, {
container.innerHTML = ""; container.innerHTML = "";
root.attachTo(container); root.attachTo(container);
// Profiler data does not contain memory allocations information.
root.toggleAllocations(false);
// When platform data isn't shown, hide the cateogry labels, since they're // When platform data isn't shown, hide the cateogry labels, since they're
// only available for C++ frames. // only available for C++ frames.
let contentOnly = !PerformanceController.getOption("show-platform-data"); let contentOnly = !PerformanceController.getOption("show-platform-data");

View File

@ -89,6 +89,13 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
// Call trees should only auto-expand when not inverted. Passing undefined // Call trees should only auto-expand when not inverted. Passing undefined
// will default to the CALL_TREE_AUTO_EXPAND depth. // will default to the CALL_TREE_AUTO_EXPAND depth.
autoExpandDepth: options.inverted ? 0 : undefined, autoExpandDepth: options.inverted ? 0 : undefined,
// Some cells like the time duration and cost percentage don't make sense
// for a memory allocations call tree.
visibleCells: {
allocations: true,
selfAllocations: true,
function: true
}
}); });
// Bind events. // Bind events.

View File

@ -509,7 +509,6 @@ let ProfileView = {
let contentOnly = !Prefs.showPlatformData; let contentOnly = !Prefs.showPlatformData;
callTreeRoot.toggleCategories(!contentOnly); callTreeRoot.toggleCategories(!contentOnly);
callTreeRoot.toggleAllocations(false);
this._callTreeRootByPanel.set(panel, callTreeRoot); this._callTreeRootByPanel.set(panel, callTreeRoot);
}, },

View File

@ -17,9 +17,20 @@ const MILLISECOND_UNITS = L10N.getStr("table.ms");
const PERCENTAGE_UNITS = L10N.getStr("table.percentage"); const PERCENTAGE_UNITS = L10N.getStr("table.percentage");
const URL_LABEL_TOOLTIP = L10N.getStr("table.url.tooltiptext"); const URL_LABEL_TOOLTIP = L10N.getStr("table.url.tooltiptext");
const ZOOM_BUTTON_TOOLTIP = L10N.getStr("table.zoom.tooltiptext"); const ZOOM_BUTTON_TOOLTIP = L10N.getStr("table.zoom.tooltiptext");
const CALL_TREE_AUTO_EXPAND = 3; // depth
const CALL_TREE_INDENTATION = 16; // px const CALL_TREE_INDENTATION = 16; // px
const DEFAULT_SORTING_PREDICATE = (a, b) => a.frame.samples < b.frame.samples ? 1 : -1; const DEFAULT_SORTING_PREDICATE = (a, b) => a.frame.samples < b.frame.samples ? 1 : -1;
const DEFAULT_AUTO_EXPAND_DEPTH = 3; // depth
const DEFAULT_VISIBLE_CELLS = {
duration: true,
percentage: true,
allocations: false,
selfDuration: true,
selfPercentage: true,
selfAllocations: false,
samples: true,
function: true
};
const clamp = (val, min, max) => Math.max(min, Math.min(max, val)); const clamp = (val, min, max) => Math.max(min, Math.min(max, val));
const sum = vals => vals.reduce((a, b) => a + b, 0); const sum = vals => vals.reduce((a, b) => a + b, 0);
@ -55,23 +66,25 @@ exports.CallView = CallView;
* top-down). Defaults to false. * top-down). Defaults to false.
* @param function sortingPredicate [optional] * @param function sortingPredicate [optional]
* The predicate used to sort the tree items when created. Defaults to * The predicate used to sort the tree items when created. Defaults to
* the caller's sortingPredicate if a caller exists, otherwise defaults * the caller's `sortingPredicate` if a caller exists, otherwise defaults
* to DEFAULT_SORTING_PREDICATE. The two passed arguments are FrameNodes. * to DEFAULT_SORTING_PREDICATE. The two passed arguments are FrameNodes.
* @param number autoExpandDepth [optional] * @param number autoExpandDepth [optional]
* The depth to which the tree should automatically expand. Defualts to * The depth to which the tree should automatically expand. Defualts to
* the caller's `autoExpandDepth` if a caller exists, otherwise defaults * the caller's `autoExpandDepth` if a caller exists, otherwise defaults
* to CALL_TREE_AUTO_EXPAND. * to DEFAULT_AUTO_EXPAND_DEPTH.
* @param object visibleCells
* An object specifying which cells are visible in the tree. Defaults to
* the caller's `visibleCells` if a caller exists, otherwise defaults
* to DEFAULT_VISIBLE_CELLS.
*/ */
function CallView({ caller, frame, level, hidden, inverted, sortingPredicate, autoExpandDepth }) { function CallView({
// Assume no indentation if this tree item's level is not specified. caller, frame, level, hidden, inverted,
level = level || 0; sortingPredicate, autoExpandDepth, visibleCells
}) {
// Don't increase indentation if this tree item is hidden. AbstractTreeItem.call(this, {
if (hidden) { parent: caller,
level--; level: level|0 - (hidden ? 1 : 0)
} });
AbstractTreeItem.call(this, { parent: caller, level });
this.sortingPredicate = sortingPredicate != null this.sortingPredicate = sortingPredicate != null
? sortingPredicate ? sortingPredicate
@ -81,7 +94,12 @@ function CallView({ caller, frame, level, hidden, inverted, sortingPredicate, au
this.autoExpandDepth = autoExpandDepth != null this.autoExpandDepth = autoExpandDepth != null
? autoExpandDepth ? autoExpandDepth
: caller ? caller.autoExpandDepth : caller ? caller.autoExpandDepth
: CALL_TREE_AUTO_EXPAND; : DEFAULT_AUTO_EXPAND_DEPTH;
this.visibleCells = visibleCells != null
? visibleCells
: caller ? caller.visibleCells
: Object.create(DEFAULT_VISIBLE_CELLS);
this.caller = caller; this.caller = caller;
this.frame = frame; this.frame = frame;
@ -110,35 +128,60 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
let totalAllocations; let totalAllocations;
if (!this._getChildCalls().length) { if (!this._getChildCalls().length) {
selfPercentage = framePercentage; if (this.visibleCells.selfPercentage) {
selfDuration = this.frame.duration; selfPercentage = framePercentage;
totalAllocations = this.frame.allocations; }
if (this.visibleCells.selfDuration) {
selfDuration = this.frame.duration;
}
if (this.visibleCells.allocations) {
totalAllocations = this.frame.allocations;
}
} else { } else {
let childrenPercentage = sum( // Avoid performing costly computations if the respective columns
[this._getPercentage(c.samples) for (c of this._getChildCalls())]); // won't be shown anyway.
let childrenDuration = sum( if (this.visibleCells.selfPercentage) {
[c.duration for (c of this._getChildCalls())]); let childrenPercentage = sum([this._getPercentage(c.samples) for (c of this._getChildCalls())]);
let childrenAllocations = sum( selfPercentage = clamp(framePercentage - childrenPercentage, 0, 100);
[c.allocations for (c of this._getChildCalls())]); }
if (this.visibleCells.selfDuration) {
selfPercentage = clamp(framePercentage - childrenPercentage, 0, 100); let childrenDuration = sum([c.duration for (c of this._getChildCalls())]);
selfDuration = this.frame.duration - childrenDuration; selfDuration = this.frame.duration - childrenDuration;
totalAllocations = this.frame.allocations + childrenAllocations; }
if (this.visibleCells.allocations) {
let childrenAllocations = sum([c.allocations for (c of this._getChildCalls())]);
totalAllocations = this.frame.allocations + childrenAllocations;
}
if (this.inverted) { if (this.inverted) {
selfPercentage = framePercentage - selfPercentage; selfPercentage = framePercentage - selfPercentage;
selfDuration = this.frame.duration - selfDuration; selfDuration = this.frame.duration - selfDuration;
} }
} }
let durationCell = this._createTimeCell(this.frame.duration); if (this.visibleCells.duration) {
let selfDurationCell = this._createTimeCell(selfDuration, true); var durationCell = this._createTimeCell(this.frame.duration);
let percentageCell = this._createExecutionCell(framePercentage); }
let selfPercentageCell = this._createExecutionCell(selfPercentage, true); if (this.visibleCells.selfDuration) {
let allocationsCell = this._createAllocationsCell(totalAllocations); var selfDurationCell = this._createTimeCell(selfDuration, true);
let selfAllocationsCell = this._createAllocationsCell(this.frame.allocations, true); }
let samplesCell = this._createSamplesCell(this.frame.samples); if (this.visibleCells.percentage) {
let functionCell = this._createFunctionCell(arrowNode, frameInfo, this.level); var percentageCell = this._createExecutionCell(framePercentage);
}
if (this.visibleCells.selfPercentage) {
var selfPercentageCell = this._createExecutionCell(selfPercentage, true);
}
if (this.visibleCells.allocations) {
var allocationsCell = this._createAllocationsCell(totalAllocations);
}
if (this.visibleCells.selfAllocations) {
var selfAllocationsCell = this._createAllocationsCell(this.frame.allocations, true);
}
if (this.visibleCells.samples) {
var samplesCell = this._createSamplesCell(this.frame.samples);
}
if (this.visibleCells.function) {
var functionCell = this._createFunctionCell(arrowNode, frameInfo, this.level);
}
let targetNode = document.createElement("hbox"); let targetNode = document.createElement("hbox");
targetNode.className = "call-tree-item"; targetNode.className = "call-tree-item";
@ -155,14 +198,30 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
functionCell.querySelector(".call-tree-category").hidden = true; functionCell.querySelector(".call-tree-category").hidden = true;
} }
targetNode.appendChild(durationCell); if (this.visibleCells.duration) {
targetNode.appendChild(percentageCell); targetNode.appendChild(durationCell);
targetNode.appendChild(allocationsCell); }
targetNode.appendChild(selfDurationCell); if (this.visibleCells.percentage) {
targetNode.appendChild(selfPercentageCell); targetNode.appendChild(percentageCell);
targetNode.appendChild(selfAllocationsCell); }
targetNode.appendChild(samplesCell); if (this.visibleCells.allocations) {
targetNode.appendChild(functionCell); targetNode.appendChild(allocationsCell);
}
if (this.visibleCells.selfDuration) {
targetNode.appendChild(selfDurationCell);
}
if (this.visibleCells.selfPercentage) {
targetNode.appendChild(selfPercentageCell);
}
if (this.visibleCells.selfAllocations) {
targetNode.appendChild(selfAllocationsCell);
}
if (this.visibleCells.samples) {
targetNode.appendChild(samplesCell);
}
if (this.visibleCells.function) {
targetNode.appendChild(functionCell);
}
return targetNode; return targetNode;
}, },
@ -301,18 +360,6 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
return cell; return cell;
}, },
/**
* Toggles the allocations information hidden or visible.
* @param boolean visible
*/
toggleAllocations: function(visible) {
if (!visible) {
this.container.setAttribute("allocations-hidden", "");
} else {
this.container.removeAttribute("allocations-hidden");
}
},
/** /**
* Toggles the category information hidden or visible. * Toggles the category information hidden or visible.
* @param boolean visible * @param boolean visible

View File

@ -124,8 +124,6 @@
overflow: auto; overflow: auto;
} }
.call-tree-cells-container[allocations-hidden] .call-tree-cell[type="allocations"],
.call-tree-cells-container[allocations-hidden] .call-tree-cell[type="self-allocations"],
.call-tree-cells-container[categories-hidden] .call-tree-category { .call-tree-cells-container[categories-hidden] .call-tree-category {
display: none; display: none;
} }

View File

@ -220,8 +220,6 @@
overflow: auto; overflow: auto;
} }
.call-tree-cells-container[allocations-hidden] .call-tree-cell[type="allocations"],
.call-tree-cells-container[allocations-hidden] .call-tree-cell[type="self-allocations"],
.call-tree-cells-container[categories-hidden] .call-tree-category { .call-tree-cells-container[categories-hidden] .call-tree-category {
display: none; display: none;
} }