Modified: trunk/Source/WebCore/inspector/Inspector.json (146586 => 146587)
--- trunk/Source/WebCore/inspector/Inspector.json 2013-03-22 10:34:33 UTC (rev 146586)
+++ trunk/Source/WebCore/inspector/Inspector.json 2013-03-22 11:00:50 UTC (rev 146587)
@@ -3106,7 +3106,8 @@
{ "name": "numberOfCalls", "type": "integer", "description": "Number of calls." },
{ "name": "visible", "type": "boolean", "description": "Visibility." },
{ "name": "callUID", "type": "number", "description": "Call UID." },
- { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." }
+ { "name": "children", "type": "array", "items": { "$ref": "CPUProfileNode" }, "description": "Child nodes." },
+ { "name": "id", "optional": true, "type": "integer", "description": "Unique id of the node." }
]
},
{
@@ -3115,7 +3116,8 @@
"description": "Profile.",
"properties": [
{ "name": "head", "$ref": "CPUProfileNode", "optional": true },
- { "name": "idleTime", "type": "number", "optional": true }
+ { "name": "idleTime", "type": "number", "optional": true },
+ { "name": "samples", "optional": true, "type": "array", "items": { "type": "integer" }, "description": "Ids of samples top nodes." }
]
},
{
Modified: trunk/Source/WebCore/inspector/front-end/CPUProfileView.js (146586 => 146587)
--- trunk/Source/WebCore/inspector/front-end/CPUProfileView.js 2013-03-22 10:34:33 UTC (rev 146586)
+++ trunk/Source/WebCore/inspector/front-end/CPUProfileView.js 2013-03-22 11:00:50 UTC (rev 146587)
@@ -122,11 +122,14 @@
return;
}
this.profileHead = profile.head;
+ this.samples = profile.samples;
if (profile.idleTime)
this._injectIdleTimeNode(profile);
this._assignParentsInProfile();
+ if (this.samples)
+ this._buildIdToNodeMap();
this._changeView();
this._updatePercentButton();
if (this.flameChart)
@@ -552,6 +555,18 @@
}
},
+ _buildIdToNodeMap: function()
+ {
+ var idToNode = this._idToNode = {};
+ var stack = [this.profileHead];
+ while (stack.length) {
+ var node = stack.pop();
+ idToNode[node.id] = node;
+ for (var i = 0; i < node.children.length; i++)
+ stack.push(node.children[i]);
+ }
+ },
+
/**
* @param {ProfilerAgent.CPUProfile} profile
*/
Modified: trunk/Source/WebCore/inspector/front-end/FlameChart.js (146586 => 146587)
--- trunk/Source/WebCore/inspector/front-end/FlameChart.js 2013-03-22 10:34:33 UTC (rev 146586)
+++ trunk/Source/WebCore/inspector/front-end/FlameChart.js 2013-03-22 11:00:50 UTC (rev 146587)
@@ -214,37 +214,22 @@
this._isDragging = false;
},
- _nodeCount: function()
+ _calculateTimelineData: function()
{
- var nodes = this._cpuProfileView.profileHead.children.slice();
+ if (this._cpuProfileView.samples)
+ return this._calculateTimelineDataForSamples();
- var nodeCount = 0;
- while (nodes.length) {
- var node = nodes.pop();
- ++nodeCount;
- nodes = nodes.concat(node.children);
- }
- return nodeCount;
- },
-
- _calculateTimelineData: function()
- {
if (this._timelineData)
return this._timelineData;
if (!this._cpuProfileView.profileHead)
return null;
- var nodeCount = this._nodeCount();
var functionColorPairs = { };
var currentColorIndex = 0;
- var startTimes = new Float32Array(nodeCount);
- var durations = new Float32Array(nodeCount);
- var depths = new Uint8Array(nodeCount);
- var nodes = new Array(nodeCount);
- var colorPairs = new Array(nodeCount);
var index = 0;
+ var entries = [];
function appendReversedArray(toArray, fromArray)
{
@@ -271,12 +256,15 @@
functionColorPairs[functionUID] = colorPair = {highlighted: "hsl(" + hue + ", 100%, 33%)", normal: "hsl(" + hue + ", 100%, 66%)"};
}
- colorPairs[index] = colorPair;
- depths[index] = level;
- durations[index] = node.totalTime;
- startTimes[index] = offset;
- nodes[index] = node;
+ entries.push({
+ colorPair: colorPair,
+ depth: level,
+ duration: node.totalTime,
+ startTime: offset,
+ node: node
+ });
+
++index;
levelOffsets[level] += node.totalTime;
@@ -293,18 +281,88 @@
}
this._timelineData = {
- nodeCount: nodeCount,
+ entries: entries,
totalTime: this._cpuProfileView.profileHead.totalTime,
- startTimes: startTimes,
- durations: durations,
- depths: depths,
- colorPairs: colorPairs,
- nodes: nodes
}
return this._timelineData;
},
+ _calculateTimelineDataForSamples: function()
+ {
+ if (this._timelineData)
+ return this._timelineData;
+
+ if (!this._cpuProfileView.profileHead)
+ return null;
+
+ var samples = this._cpuProfileView.samples;
+ var idToNode = this._cpuProfileView._idToNode;
+ var samplesCount = samples.length;
+ var functionColorPairs = { };
+ var currentColorIndex = 0;
+
+ var index = 0;
+ var entries = [];
+
+ var openIntervals = [];
+ var stackTrace = [];
+ for (var sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++) {
+ var node = idToNode[samples[sampleIndex]];
+ stackTrace.length = 0;
+ while (node) {
+ stackTrace.push(node);
+ node = node.parent;
+ }
+ stackTrace.pop(); // Remove (root) node
+
+ var depth = 0;
+ node = stackTrace.pop();
+ while (node && depth < openIntervals.length && node === openIntervals[depth].node) {
+ var intervalIndex = openIntervals[depth].index;
+ entries[intervalIndex].duration += 1;
+ node = stackTrace.pop();
+ ++depth;
+ }
+ if (depth < openIntervals.length)
+ openIntervals.length = depth;
+ if (!node)
+ continue;
+
+ while (node) {
+ var functionUID = node.functionName + ":" + node.url + ":" + node.lineNumber;
+ var colorPair = functionColorPairs[functionUID];
+ if (!colorPair) {
+ ++currentColorIndex;
+ var hue = (currentColorIndex * 5 + 11 * (currentColorIndex % 2)) % 360;
+ functionColorPairs[functionUID] = colorPair = {highlighted: "hsl(" + hue + ", 100%, 33%)", normal: "hsl(" + hue + ", 100%, 66%)"};
+ }
+
+ entries.push({
+ colorPair: colorPair,
+ depth: depth,
+ duration: 1,
+ startTime: sampleIndex,
+ node: node
+ });
+
+ openIntervals.push({node: node, index: index});
+
+ ++index;
+
+ node = stackTrace.pop();
+ ++depth;
+ }
+ }
+
+ this._timelineData = {
+ entries: entries,
+ totalTime: samplesCount,
+ };
+
+ return this._timelineData;
+ },
+
_getPopoverAnchor: function()
{
if (this._highlightedNodeIndex === -1 || this._isDragging)
@@ -316,7 +374,7 @@
{
if (this._isDragging)
return;
- var node = this._timelineData.nodes[this._highlightedNodeIndex];
+ var node = this._timelineData.entries[this._highlightedNodeIndex].node;
if (!node)
return;
var contentHelper = new WebInspector.PopoverContentHelper(node.functionName);
@@ -342,7 +400,7 @@
{
if (this._highlightedNodeIndex === -1)
return;
- var node = this._timelineData.nodes[this._highlightedNodeIndex];
+ var node = this._timelineData.entries[this._highlightedNodeIndex].node;
this.dispatchEventToListeners(WebInspector.FlameChart.Events.SelectedNode, node);
},
@@ -359,19 +417,20 @@
if (nodeIndex === -1)
return;
- var timelineData = this._timelineData;
+ var timelineEntries = this._timelineData.entries;
- var anchorLeft = Math.floor(timelineData.startTimes[nodeIndex] * this._timeToPixel - this._pixelWindowLeft);
+ var anchorLeft = Math.floor(timelineEntries[nodeIndex].startTime * this._timeToPixel - this._pixelWindowLeft);
anchorLeft = Number.constrain(anchorLeft, 0, this._canvas.width);
- var anchorWidth = Math.floor(timelineData.durations[nodeIndex] * this._timeToPixel);
+ var anchorWidth = Math.floor(timelineEntries[nodeIndex].duration * this._timeToPixel);
+
anchorWidth = Number.constrain(anchorWidth, 0, this._canvas.width - anchorLeft);
var style = this._anchorElement.style;
style.width = anchorWidth + "px";
style.height = this._barHeight + "px";
style.left = anchorLeft + "px";
- style.top = Math.floor(this._canvas.height - (timelineData.depths[nodeIndex] + 1) * this._barHeight) + "px";
+ style.top = Math.floor(this._canvas.height - (timelineEntries[nodeIndex].depth + 1) * this._barHeight) + "px";
},
_onMouseWheel: function(e)
@@ -390,14 +449,15 @@
var timelineData = this._timelineData;
if (!timelineData)
return -1;
+ var timelineEntries = timelineData.entries;
var cursorTime = Math.floor((x + this._pixelWindowLeft) * this._pixelToTime);
var cursorLevel = Math.floor((this._canvas.height - y) / this._barHeight);
- for (var i = 0; i < timelineData.nodeCount; ++i) {
- if (cursorTime < timelineData.startTimes[i])
+ for (var i = 0; i < timelineEntries.length; ++i) {
+ if (cursorTime < timelineEntries[i].startTime)
return -1;
- if (cursorTime < (timelineData.startTimes[i] + timelineData.durations[i])
- && cursorLevel === timelineData.depths[i])
+ if (cursorTime < (timelineEntries[i].startTime + timelineEntries[i].duration)
+ && cursorLevel === timelineEntries[i].depth)
return i;
}
return -1;
@@ -418,18 +478,17 @@
if (!this._timelineData)
return;
- var nodeCount = this._timelineData.nodeCount;
- var depths = this._timelineData.depths;
- var startTimes = this._timelineData.startTimes;
- var durations = this._timelineData.durations;
+ var timelineEntries = this._timelineData.entries;
+
var drawData = new Uint8Array(width);
var scaleFactor = width / this._totalTime;
- for (var nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex) {
- var start = Math.floor(startTimes[nodeIndex] * scaleFactor);
- var finish = Math.floor((startTimes[nodeIndex] + durations[nodeIndex]) * scaleFactor);
+ for (var nodeIndex = 0; nodeIndex < timelineEntries.length; ++nodeIndex) {
+ var entry = timelineEntries[nodeIndex];
+ var start = Math.floor(entry.startTime * scaleFactor);
+ var finish = Math.floor((entry.startTime + entry.duration) * scaleFactor);
for (var x = start; x < finish; ++x)
- drawData[x] = Math.max(drawData[x], depths[nodeIndex] + 1);
+ drawData[x] = Math.max(drawData[x], entry.depth + 1);
}
var context = this._overviewCanvas.getContext("2d");
@@ -456,25 +515,26 @@
var timelineData = this._calculateTimelineData();
if (!timelineData)
return;
+ var timelineEntries = timelineData.entries;
this._canvas.height = height;
this._canvas.width = width;
var barHeight = this._barHeight;
var context = this._canvas.getContext("2d");
- for (var i = 0; i < timelineData.nodeCount; ++i) {
- var startTime = timelineData.startTimes[i];
+ for (var i = 0; i < timelineEntries.length; ++i) {
+ var startTime = timelineEntries[i].startTime;
if (startTime > this._timeWindowRight)
break;
- if ((startTime + timelineData.durations[i]) < this._timeWindowLeft)
+ if ((startTime + timelineEntries[i].duration) < this._timeWindowLeft)
continue;
var x = Math.floor(startTime * this._timeToPixel) - this._pixelWindowLeft;
- var y = height - (timelineData.depths[i] + 1) * barHeight;
- var barWidth = Math.floor(timelineData.durations[i] * this._timeToPixel);
+ var y = height - (timelineEntries[i].depth + 1) * barHeight;
+ var barWidth = Math.floor(timelineEntries[i].duration * this._timeToPixel);
if (barWidth < this._minWidth)
continue;
- var colorPair = timelineData.colorPairs[i];
+ var colorPair = timelineEntries[i].colorPair;
var color;
if (this._highlightedNodeIndex === i)
color = colorPair.highlighted;