Bug 1074899 - Add self time and self percentage to the profiler. r=vporof

This commit is contained in:
Nick Fitzgerald 2014-10-01 07:54:00 -04:00
parent cd2741e613
commit 318b30af30
6 changed files with 83 additions and 29 deletions

View File

@ -107,11 +107,19 @@
<label class="plain call-tree-header"
type="duration"
crop="end"
value="&profilerUI.table.duration;"/>
value="&profilerUI.table.totalDuration;"/>
<label class="plain call-tree-header"
type="self-duration"
crop="end"
value="&profilerUI.table.selfDuration;"/>
<label class="plain call-tree-header"
type="percentage"
crop="end"
value="&profilerUI.table.percentage;"/>
value="&profilerUI.table.totalPercentage;"/>
<label class="plain call-tree-header"
type="self-percentage"
crop="end"
value="&profilerUI.table.selfPercentage;"/>
<label class="plain call-tree-header"
type="samples"
crop="end"

View File

@ -22,9 +22,9 @@ function test() {
is(container.childNodes[0].className, "call-tree-item",
"The root node in the tree has the correct class name.");
is(container.childNodes[0].childNodes.length, 4,
is(container.childNodes[0].childNodes.length, 6,
"The root node in the tree has the correct number of children.");
is(container.childNodes[0].querySelectorAll(".call-tree-cell").length, 4,
is(container.childNodes[0].querySelectorAll(".call-tree-cell").length, 6,
"The root node in the tree has only 'call-tree-cell' children.");
is(container.childNodes[0].childNodes[0].getAttribute("type"), "duration",
@ -32,19 +32,29 @@ function test() {
is(container.childNodes[0].childNodes[0].getAttribute("value"), "18",
"The root node in the tree has the correct duration cell value.");
is(container.childNodes[0].childNodes[1].getAttribute("type"), "percentage",
is(container.childNodes[0].childNodes[1].getAttribute("type"), "self-duration",
"The root node in the tree has a self-duration cell.");
is(container.childNodes[0].childNodes[1].getAttribute("value"), "0",
"The root node in the tree has the correct self-duration cell value.");
is(container.childNodes[0].childNodes[2].getAttribute("type"), "percentage",
"The root node in the tree has a percentage cell.");
is(container.childNodes[0].childNodes[1].getAttribute("value"), "100%",
is(container.childNodes[0].childNodes[2].getAttribute("value"), "100%",
"The root node in the tree has the correct percentage cell value.");
is(container.childNodes[0].childNodes[2].getAttribute("type"), "samples",
is(container.childNodes[0].childNodes[3].getAttribute("type"), "self-percentage",
"The root node in the tree has a self-percentage cell.");
is(container.childNodes[0].childNodes[3].getAttribute("value"), "0%",
"The root node in the tree has the correct self-percentage cell value.");
is(container.childNodes[0].childNodes[4].getAttribute("type"), "samples",
"The root node in the tree has an samples cell.");
is(container.childNodes[0].childNodes[2].getAttribute("value"), "3",
is(container.childNodes[0].childNodes[4].getAttribute("value"), "3",
"The root node in the tree has the correct samples cell value.");
is(container.childNodes[0].childNodes[3].getAttribute("type"), "function",
is(container.childNodes[0].childNodes[5].getAttribute("type"), "function",
"The root node in the tree has a function cell.");
is(container.childNodes[0].childNodes[3].style.MozMarginStart, "0px",
is(container.childNodes[0].childNodes[5].style.MozMarginStart, "0px",
"The root node in the tree has the correct indentation.");
finish();

View File

@ -42,18 +42,22 @@ function test() {
ok(!A.target.querySelector(".call-tree-category").hidden,
"The .A.B.C node's category label cell should not be hidden.");
is(C.target.childNodes.length, 4,
is(C.target.childNodes.length, 6,
"The number of columns displayed for tree items is correct.");
is(C.target.childNodes[0].getAttribute("type"), "duration",
"The first column displayed for tree items is correct.");
is(C.target.childNodes[1].getAttribute("type"), "percentage",
is(C.target.childNodes[1].getAttribute("type"), "self-duration",
"The second column displayed for tree items is correct.");
is(C.target.childNodes[2].getAttribute("type"), "samples",
is(C.target.childNodes[2].getAttribute("type"), "percentage",
"The third column displayed for tree items is correct.");
is(C.target.childNodes[3].getAttribute("type"), "function",
is(C.target.childNodes[3].getAttribute("type"), "self-percentage",
"The fourth column displayed for tree items is correct.");
is(C.target.childNodes[4].getAttribute("type"), "samples",
"The fifth column displayed for tree items is correct.");
is(C.target.childNodes[5].getAttribute("type"), "function",
"The sixth column displayed for tree items is correct.");
let functionCell = C.target.childNodes[3];
let functionCell = C.target.childNodes[5];
is(functionCell.childNodes.length, 8,
"The number of columns displayed for function cells is correct.");

View File

@ -18,6 +18,9 @@ const ZOOM_BUTTON_TOOLTIP = L10N.getStr("table.zoom.tooltiptext");
const CALL_TREE_INDENTATION = 16; // px
const CALL_TREE_AUTO_EXPAND = 3; // depth
const clamp = (val, min, max) => Math.max(min, Math.min(max, val));
const sum = vals => vals.reduce((a, b) => a + b, 0);
exports.CallView = CallView;
/**
@ -63,10 +66,17 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
this.document = document;
let frameInfo = this.frame.getInfo();
let framePercentage = this.frame.samples / this.root.frame.samples * 100;
let framePercentage = this._getPercentage(this.frame.samples);
let childrenPercentage = sum([this._getPercentage(c.samples)
for (c of this._getChildCalls())]);
let selfPercentage = clamp(framePercentage - childrenPercentage, 0, 100);
let selfDuration = this.frame.duration - sum([c.duration
for (c of this._getChildCalls())]);
let durationCell = this._createTimeCell(this.frame.duration);
let selfDurationCell = this._createTimeCell(selfDuration, true);
let percentageCell = this._createExecutionCell(framePercentage);
let selfPercentageCell = this._createExecutionCell(selfPercentage, true);
let samplesCell = this._createSamplesCell(this.frame.samples);
let functionCell = this._createFunctionCell(arrowNode, frameInfo, this.level);
@ -83,13 +93,29 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
}
targetNode.appendChild(durationCell);
targetNode.appendChild(selfDurationCell);
targetNode.appendChild(percentageCell);
targetNode.appendChild(selfPercentageCell);
targetNode.appendChild(samplesCell);
targetNode.appendChild(functionCell);
return targetNode;
},
/**
* Calculate what percentage of all samples the given number of samples is.
*/
_getPercentage: function (samples) {
return samples / this.root.frame.samples * 100;
},
/**
* Return an array of this frame's child calls.
*/
_getChildCalls: function () {
return Object.keys(this.frame.calls).map(k => this.frame.calls[k]);
},
/**
* Populates this node in the call tree with the corresponding "callees".
* These are defined in the `frame` data source for this call view.
@ -98,7 +124,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
_populateSelf: function(children) {
let newLevel = this.level + 1;
for (let [, newFrame] of _Iterator(this.frame.calls)) {
for (let newFrame of this._getChildCalls()) {
children.push(new CallView({
caller: this,
frame: newFrame,
@ -114,18 +140,18 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
* Functions creating each cell in this call view.
* Invoked by `_displaySelf`.
*/
_createTimeCell: function(duration) {
_createTimeCell: function(duration, isSelf = false) {
let cell = this.document.createElement("label");
cell.className = "plain call-tree-cell";
cell.setAttribute("type", "duration");
cell.setAttribute("type", isSelf ? "self-duration" : "duration");
cell.setAttribute("crop", "end");
cell.setAttribute("value", L10N.numberWithDecimals(duration, 2));
return cell;
},
_createExecutionCell: function(percentage) {
_createExecutionCell: function(percentage, isSelf = false) {
let cell = this.document.createElement("label");
cell.className = "plain call-tree-cell";
cell.setAttribute("type", "percentage");
cell.setAttribute("type", isSelf ? "self-percentage" : "percentage");
cell.setAttribute("crop", "end");
cell.setAttribute("value", L10N.numberWithDecimals(percentage, 2) + "%");
return cell;

View File

@ -39,10 +39,12 @@
<!-- LOCALIZATION NOTE (profilerUI.table.*): These strings are displayed
- in the call tree headers for a recording. -->
<!ENTITY profilerUI.table.duration "Time (ms)">
<!ENTITY profilerUI.table.percentage "Cost">
<!ENTITY profilerUI.table.samples "Samples">
<!ENTITY profilerUI.table.function "Function">
<!ENTITY profilerUI.table.totalDuration "Total Time (ms)">
<!ENTITY profilerUI.table.selfDuration "Self Time (ms)">
<!ENTITY profilerUI.table.totalPercentage "Total Cost">
<!ENTITY profilerUI.table.selfPercentage "Self Cost">
<!ENTITY profilerUI.table.samples "Samples">
<!ENTITY profilerUI.table.function "Function">
<!-- LOCALIZATION NOTE (profilerUI.newtab.tooltiptext): The tooltiptext shown
- on the "+" (new tab) button for a profile when a selection is available. -->

View File

@ -251,13 +251,17 @@
}
.call-tree-header[type="duration"],
.call-tree-cell[type="duration"] {
width: 7em;
.call-tree-cell[type="duration"],
.call-tree-header[type="self-duration"],
.call-tree-cell[type="self-duration"] {
width: 9em;
}
.call-tree-header[type="percentage"],
.call-tree-cell[type="percentage"] {
width: 5em;
.call-tree-cell[type="percentage"],
.call-tree-header[type="self-percentage"],
.call-tree-cell[type="self-percentage"] {
width: 6em;
}
.call-tree-header[type="samples"],