| Index: Source/devtools/front_end/CPUProfileView.js
|
| diff --git a/Source/devtools/front_end/CPUProfileView.js b/Source/devtools/front_end/CPUProfileView.js
|
| index 1f2cfea939b4d417893d4c28497e96288548d6fd..f6b0656fcc2d98fa8bb15d43166b30e85e063421 100644
|
| --- a/Source/devtools/front_end/CPUProfileView.js
|
| +++ b/Source/devtools/front_end/CPUProfileView.js
|
| @@ -26,94 +26,6 @@
|
|
|
| /**
|
| * @constructor
|
| - * @param {!ProfilerAgent.CPUProfile} profile
|
| - */
|
| -WebInspector.CPUProfileDataModel = function(profile)
|
| -{
|
| - this.profileHead = profile.head;
|
| - this.samples = profile.samples;
|
| - this._calculateTimes(profile);
|
| - this._assignParentsInProfile();
|
| - if (this.samples)
|
| - this._buildIdToNodeMap();
|
| -}
|
| -
|
| -WebInspector.CPUProfileDataModel.prototype = {
|
| - /**
|
| - * @param {!ProfilerAgent.CPUProfile} profile
|
| - */
|
| - _calculateTimes: function(profile)
|
| - {
|
| - function totalHitCount(node) {
|
| - var result = node.hitCount;
|
| - for (var i = 0; i < node.children.length; i++)
|
| - result += totalHitCount(node.children[i]);
|
| - return result;
|
| - }
|
| - profile.totalHitCount = totalHitCount(profile.head);
|
| -
|
| - var durationMs = 1000 * (profile.endTime - profile.startTime);
|
| - var samplingInterval = durationMs / profile.totalHitCount;
|
| - this.samplingIntervalMs = samplingInterval;
|
| -
|
| - function calculateTimesForNode(node) {
|
| - node.selfTime = node.hitCount * samplingInterval;
|
| - var totalHitCount = node.hitCount;
|
| - for (var i = 0; i < node.children.length; i++)
|
| - totalHitCount += calculateTimesForNode(node.children[i]);
|
| - node.totalTime = totalHitCount * samplingInterval;
|
| - return totalHitCount;
|
| - }
|
| - calculateTimesForNode(profile.head);
|
| - },
|
| -
|
| - _assignParentsInProfile: function()
|
| - {
|
| - var head = this.profileHead;
|
| - head.parent = null;
|
| - head.head = null;
|
| - var nodesToTraverse = [ head ];
|
| - while (nodesToTraverse.length) {
|
| - var parent = nodesToTraverse.pop();
|
| - var children = parent.children;
|
| - var length = children.length;
|
| - for (var i = 0; i < length; ++i) {
|
| - var child = children[i];
|
| - child.head = head;
|
| - child.parent = parent;
|
| - if (child.children.length)
|
| - nodesToTraverse.push(child);
|
| - }
|
| - }
|
| - },
|
| -
|
| - _buildIdToNodeMap: function()
|
| - {
|
| - /** @type {!Object.<number, !ProfilerAgent.CPUProfileNode>} */
|
| - this._idToNode = {};
|
| - 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]);
|
| - }
|
| -
|
| - var topLevelNodes = this.profileHead.children;
|
| - for (var i = 0; i < topLevelNodes.length; i++) {
|
| - var node = topLevelNodes[i];
|
| - if (node.functionName === "(garbage collector)") {
|
| - this._gcNode = node;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -/**
|
| - * @constructor
|
| * @extends {WebInspector.VBox}
|
| * @param {!WebInspector.CPUProfileHeader} profileHeader
|
| */
|
| @@ -996,356 +908,3 @@ WebInspector.CPUProfileView.colorGenerator = function()
|
| }
|
| return WebInspector.CPUProfileView._colorGenerator;
|
| }
|
| -
|
| -/**
|
| - * @constructor
|
| - * @implements {WebInspector.FlameChartDataProvider}
|
| - * @param {!WebInspector.CPUProfileDataModel} cpuProfile
|
| - * @param {!WebInspector.Target} target
|
| - */
|
| -WebInspector.CPUFlameChartDataProvider = function(cpuProfile, target)
|
| -{
|
| - WebInspector.FlameChartDataProvider.call(this);
|
| - this._cpuProfile = cpuProfile;
|
| - this._target = target;
|
| - this._colorGenerator = WebInspector.CPUProfileView.colorGenerator();
|
| -}
|
| -
|
| -WebInspector.CPUFlameChartDataProvider.prototype = {
|
| - /**
|
| - * @return {number}
|
| - */
|
| - barHeight: function()
|
| - {
|
| - return 15;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - textBaseline: function()
|
| - {
|
| - return 4;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - textPadding: function()
|
| - {
|
| - return 2;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} startTime
|
| - * @param {number} endTime
|
| - * @return {?Array.<number>}
|
| - */
|
| - dividerOffsets: function(startTime, endTime)
|
| - {
|
| - return null;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - zeroTime: function()
|
| - {
|
| - return 0;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - totalTime: function()
|
| - {
|
| - return this._cpuProfile.profileHead.totalTime;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - maxStackDepth: function()
|
| - {
|
| - return this._maxStackDepth;
|
| - },
|
| -
|
| - /**
|
| - * @return {?WebInspector.FlameChart.TimelineData}
|
| - */
|
| - timelineData: function()
|
| - {
|
| - return this._timelineData || this._calculateTimelineData();
|
| - },
|
| -
|
| - /**
|
| - * @return {?WebInspector.FlameChart.TimelineData}
|
| - */
|
| - _calculateTimelineData: function()
|
| - {
|
| - if (!this._cpuProfile.profileHead)
|
| - return null;
|
| -
|
| - var samples = this._cpuProfile.samples;
|
| - var idToNode = this._cpuProfile._idToNode;
|
| - var gcNode = this._cpuProfile._gcNode;
|
| - var samplesCount = samples.length;
|
| - var samplingInterval = this._cpuProfile.samplingIntervalMs;
|
| -
|
| - var index = 0;
|
| -
|
| - var openIntervals = [];
|
| - var stackTrace = [];
|
| - var maxDepth = 5; // minimum stack depth for the case when we see no activity.
|
| - var depth = 0;
|
| -
|
| - /**
|
| - * @constructor
|
| - * @param {number} depth
|
| - * @param {number} duration
|
| - * @param {number} startTime
|
| - * @param {!Object} node
|
| - */
|
| - function ChartEntry(depth, duration, startTime, node)
|
| - {
|
| - this.depth = depth;
|
| - this.duration = duration;
|
| - this.startTime = startTime;
|
| - this.node = node;
|
| - this.selfTime = 0;
|
| - }
|
| - var entries = /** @type {!Array.<!ChartEntry>} */ ([]);
|
| -
|
| - 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
|
| -
|
| - maxDepth = Math.max(maxDepth, depth);
|
| - depth = 0;
|
| - node = stackTrace.pop();
|
| - var intervalIndex;
|
| -
|
| - // GC samples have no stack, so we just put GC node on top of the last recoreded sample.
|
| - if (node === gcNode) {
|
| - while (depth < openIntervals.length) {
|
| - intervalIndex = openIntervals[depth].index;
|
| - entries[intervalIndex].duration += samplingInterval;
|
| - ++depth;
|
| - }
|
| - // If previous stack is also GC then just continue.
|
| - if (openIntervals.length > 0 && openIntervals.peekLast().node === node) {
|
| - entries[intervalIndex].selfTime += samplingInterval;
|
| - continue;
|
| - }
|
| - }
|
| -
|
| - while (node && depth < openIntervals.length && node === openIntervals[depth].node) {
|
| - intervalIndex = openIntervals[depth].index;
|
| - entries[intervalIndex].duration += samplingInterval;
|
| - node = stackTrace.pop();
|
| - ++depth;
|
| - }
|
| - if (depth < openIntervals.length)
|
| - openIntervals.length = depth;
|
| - if (!node) {
|
| - entries[intervalIndex].selfTime += samplingInterval;
|
| - continue;
|
| - }
|
| -
|
| - var colorGenerator = this._colorGenerator;
|
| - var color = "";
|
| - while (node) {
|
| - entries.push(new ChartEntry(depth, samplingInterval, sampleIndex * samplingInterval, node));
|
| - openIntervals.push({node: node, index: index});
|
| - ++index;
|
| -
|
| - node = stackTrace.pop();
|
| - ++depth;
|
| - }
|
| - entries[entries.length - 1].selfTime += samplingInterval;
|
| - }
|
| -
|
| - /** @type {!Array.<!ProfilerAgent.CPUProfileNode>} */
|
| - var entryNodes = new Array(entries.length);
|
| - var entryLevels = new Uint8Array(entries.length);
|
| - var entryTotalTimes = new Float32Array(entries.length);
|
| - var entrySelfTimes = new Float32Array(entries.length);
|
| - var entryOffsets = new Float32Array(entries.length);
|
| -
|
| - for (var i = 0; i < entries.length; ++i) {
|
| - var entry = entries[i];
|
| - entryNodes[i] = entry.node;
|
| - entryLevels[i] = entry.depth;
|
| - entryTotalTimes[i] = entry.duration;
|
| - entryOffsets[i] = entry.startTime;
|
| - entrySelfTimes[i] = entry.selfTime;
|
| - }
|
| -
|
| - this._maxStackDepth = Math.max(maxDepth, depth);
|
| -
|
| - this._timelineData = {
|
| - entryLevels: entryLevels,
|
| - entryTotalTimes: entryTotalTimes,
|
| - entryOffsets: entryOffsets,
|
| - };
|
| -
|
| - /** @type {!Array.<!ProfilerAgent.CPUProfileNode>} */
|
| - this._entryNodes = entryNodes;
|
| - this._entrySelfTimes = entrySelfTimes;
|
| -
|
| - return /** @type {!WebInspector.FlameChart.TimelineData} */ (this._timelineData);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} ms
|
| - * @return {string}
|
| - */
|
| - _millisecondsToString: function(ms)
|
| - {
|
| - if (ms === 0)
|
| - return "0";
|
| - if (ms < 1000)
|
| - return WebInspector.UIString("%.1f\u2009ms", ms);
|
| - return Number.secondsToString(ms / 1000, true);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {?Array.<!{title: string, text: string}>}
|
| - */
|
| - prepareHighlightedEntryInfo: function(entryIndex)
|
| - {
|
| - var timelineData = this._timelineData;
|
| - var node = this._entryNodes[entryIndex];
|
| - if (!node)
|
| - return null;
|
| -
|
| - var entryInfo = [];
|
| - function pushEntryInfoRow(title, text)
|
| - {
|
| - var row = {};
|
| - row.title = title;
|
| - row.text = text;
|
| - entryInfo.push(row);
|
| - }
|
| -
|
| - pushEntryInfoRow(WebInspector.UIString("Name"), node.functionName);
|
| - var selfTime = this._millisecondsToString(this._entrySelfTimes[entryIndex]);
|
| - var totalTime = this._millisecondsToString(timelineData.entryTotalTimes[entryIndex]);
|
| - pushEntryInfoRow(WebInspector.UIString("Self time"), selfTime);
|
| - pushEntryInfoRow(WebInspector.UIString("Total time"), totalTime);
|
| - var target = this._target;
|
| - var text = WebInspector.Linkifier.liveLocationText(target, node.scriptId, node.lineNumber, node.columnNumber);
|
| - pushEntryInfoRow(WebInspector.UIString("URL"), text);
|
| - pushEntryInfoRow(WebInspector.UIString("Aggregated self time"), Number.secondsToString(node.selfTime / 1000, true));
|
| - pushEntryInfoRow(WebInspector.UIString("Aggregated total time"), Number.secondsToString(node.totalTime / 1000, true));
|
| - if (node.deoptReason && node.deoptReason !== "no reason")
|
| - pushEntryInfoRow(WebInspector.UIString("Not optimized"), node.deoptReason);
|
| -
|
| - return entryInfo;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {boolean}
|
| - */
|
| - canJumpToEntry: function(entryIndex)
|
| - {
|
| - return this._entryNodes[entryIndex].scriptId !== "0";
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {?string}
|
| - */
|
| - entryTitle: function(entryIndex)
|
| - {
|
| - var node = this._entryNodes[entryIndex];
|
| - return node.functionName;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {?string}
|
| - */
|
| - entryFont: function(entryIndex)
|
| - {
|
| - if (!this._font) {
|
| - this._font = (this.barHeight() - 4) + "px " + WebInspector.fontFamily();
|
| - this._boldFont = "bold " + this._font;
|
| - }
|
| - var node = this._entryNodes[entryIndex];
|
| - var reason = node.deoptReason;
|
| - return (reason && reason !== "no reason") ? this._boldFont : this._font;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {!string}
|
| - */
|
| - entryColor: function(entryIndex)
|
| - {
|
| - var node = this._entryNodes[entryIndex];
|
| - return this._colorGenerator.colorForID(node.functionName + ":" + node.url + ":" + node.lineNumber);
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @param {!CanvasRenderingContext2D} context
|
| - * @param {?string} text
|
| - * @param {number} barX
|
| - * @param {number} barY
|
| - * @param {number} barWidth
|
| - * @param {number} barHeight
|
| - * @param {function(number):number} offsetToPosition
|
| - * @return {boolean}
|
| - */
|
| - decorateEntry: function(entryIndex, context, text, barX, barY, barWidth, barHeight, offsetToPosition)
|
| - {
|
| - return false;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {boolean}
|
| - */
|
| - forceDecoration: function(entryIndex)
|
| - {
|
| - return false;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {!{startTimeOffset: number, endTimeOffset: number}}
|
| - */
|
| - highlightTimeRange: function(entryIndex)
|
| - {
|
| - var startTimeOffset = this._timelineData.entryOffsets[entryIndex];
|
| - return {
|
| - startTimeOffset: startTimeOffset,
|
| - endTimeOffset: startTimeOffset + this._timelineData.entryTotalTimes[entryIndex]
|
| - };
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - paddingLeft: function()
|
| - {
|
| - return 15;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} entryIndex
|
| - * @return {!string}
|
| - */
|
| - textColor: function(entryIndex)
|
| - {
|
| - return "#333";
|
| - }
|
| -}
|
|
|