diff options
Diffstat (limited to 'Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js')
-rw-r--r-- | Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js | 204 |
1 files changed, 200 insertions, 4 deletions
diff --git a/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js b/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js index 2f709fe23..1dfb21aa4 100644 --- a/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js +++ b/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js @@ -35,9 +35,13 @@ WebInspector.NativeMemorySnapshotView = function(profile) { WebInspector.View.call(this); - this.element.addStyleClass("memory-chart-view"); - this.element.createChild("div").textContent = "Memory chart"; + this.registerRequiredCSS("nativeMemoryProfiler.css"); this._profile = profile; + this.element.addStyleClass("memory-chart-view"); + + var pieChart = new WebInspector.NativeMemoryPieChart(profile._memoryBlock); + pieChart.element.addStyleClass("fill"); + pieChart.show(this.element); } WebInspector.NativeMemorySnapshotView.prototype = { @@ -65,7 +69,7 @@ WebInspector.NativeMemorySnapshotView.prototype.__proto__ = WebInspector.View.pr WebInspector.NativeMemoryProfileType = function() { WebInspector.ProfileType.call(this, WebInspector.NativeMemoryProfileType.TypeId, WebInspector.UIString("Take Native Memory Snapshot")); - this._profileIndex = 1; + this._nextProfileUid = 1; } WebInspector.NativeMemoryProfileType.TypeId = "NATIVE_MEMORY"; @@ -83,8 +87,16 @@ WebInspector.NativeMemoryProfileType.prototype = { buttonClicked: function() { var profilesPanel = WebInspector.panels.profiles; - var profileHeader = new WebInspector.NativeMemoryProfileHeader(this, WebInspector.UIString("Snapshot %d", this._profileIndex++), -1); + var profileHeader = new WebInspector.NativeMemoryProfileHeader(this, WebInspector.UIString("Snapshot %d", this._nextProfileUid), this._nextProfileUid); + ++this._nextProfileUid; + profileHeader.isTemporary = true; profilesPanel.addProfileHeader(profileHeader); + function didReceiveMemorySnapshot(error, memoryBlock) + { + profileHeader._memoryBlock = memoryBlock; + profileHeader.isTemporary = false; + } + MemoryAgent.getProcessMemoryDistribution(didReceiveMemorySnapshot.bind(this)); return false; }, @@ -132,6 +144,11 @@ WebInspector.NativeMemoryProfileType.prototype.__proto__ = WebInspector.ProfileT WebInspector.NativeMemoryProfileHeader = function(type, title, uid) { WebInspector.ProfileHeader.call(this, type, title, uid); + + /** + * @type {MemoryAgent.MemoryBlock} + */ + this._memoryBlock = null; } WebInspector.NativeMemoryProfileHeader.prototype = { @@ -153,3 +170,182 @@ WebInspector.NativeMemoryProfileHeader.prototype = { } WebInspector.NativeMemoryProfileHeader.prototype.__proto__ = WebInspector.ProfileHeader.prototype; + +/** + * @constructor + * @param {string} fillStyle + * @param {string} name + * @param {string} description + */ +WebInspector.MemoryBlockViewProperties = function(fillStyle, name, description) +{ + this._fillStyle = fillStyle; + this._name = name; + this._description = description; +} + +/** + * @type {Object.<string, WebInspector.MemoryBlockViewProperties>} + */ +WebInspector.MemoryBlockViewProperties._standardBlocks = null; + +WebInspector.MemoryBlockViewProperties._initialize = function() +{ + if (WebInspector.MemoryBlockViewProperties._standardBlocks) + return; + WebInspector.MemoryBlockViewProperties._standardBlocks = {}; + function addBlock(fillStyle, name, description) + { + WebInspector.MemoryBlockViewProperties._standardBlocks[name] = new WebInspector.MemoryBlockViewProperties(fillStyle, name, WebInspector.UIString(description)); + } + addBlock("rgba(240, 240, 250, 0.8)", "ProcessPrivateMemory", "Total"); + addBlock("rgba(250, 200, 200, 0.8)", "JSHeapAllocated", "JavaScript heap"); + addBlock("rgba(200, 250, 200, 0.8)", "JSHeapUsed", "Used JavaScript heap"); +} + +WebInspector.MemoryBlockViewProperties._forMemoryBlock = function(memoryBlock) +{ + WebInspector.MemoryBlockViewProperties._initialize(); + var result = WebInspector.MemoryBlockViewProperties._standardBlocks[memoryBlock.name]; + if (result) + return result; + return new WebInspector.MemoryBlockViewProperties("rgba(20, 200, 20, 0.8)", memoryBlock.name, memoryBlock.name); +} + + +/** + * @constructor + * @extends {WebInspector.View} + * @param {MemoryAgent.MemoryBlock} memorySnapshot + */ +WebInspector.NativeMemoryPieChart = function(memorySnapshot) +{ + WebInspector.View.call(this); + this._memorySnapshot = memorySnapshot; + this.element = document.createElement("div"); + this.element.addStyleClass("memory-pie-chart-container"); + this._memoryBlockList = this.element.createChild("div", "memory-blocks-list"); + + this._canvasContainer = this.element.createChild("div", "memory-pie-chart"); + this._canvas = this._canvasContainer.createChild("canvas"); + this._addBlockLabels(memorySnapshot, true); +} + +WebInspector.NativeMemoryPieChart.prototype = { + /** + * @override + */ + onResize: function() + { + this._updateSize(); + this._paint(); + }, + + _updateSize: function() + { + var width = this._canvasContainer.clientWidth - 5; + var height = this._canvasContainer.clientHeight - 5; + this._canvas.width = width; + this._canvas.height = height; + }, + + _addBlockLabels: function(memoryBlock, includeChildren) + { + var viewProperties = WebInspector.MemoryBlockViewProperties._forMemoryBlock(memoryBlock); + var title = viewProperties._description + ": " + Number.bytesToString(memoryBlock.size); + + var swatchElement = this._memoryBlockList.createChild("div", "item"); + swatchElement.createChild("div", "swatch").style.backgroundColor = viewProperties._fillStyle; + swatchElement.createChild("span", "title").textContent = WebInspector.UIString(title); + + if (!memoryBlock.children || !includeChildren) + return; + for (var i = 0; i < memoryBlock.children.length; i++) + this._addBlockLabels(memoryBlock.children[i], false); + }, + + _paint: function() + { + this._clear(); + var width = this._canvas.width; + var height = this._canvas.height; + + var x = width / 2; + var y = height / 2; + var radius = 200; + + var ctx = this._canvas.getContext("2d"); + ctx.beginPath(); + ctx.arc(x, y, radius, 0, Math.PI*2, false); + ctx.lineWidth = 1; + ctx.fillStyle = WebInspector.MemoryBlockViewProperties._forMemoryBlock(this._memorySnapshot)._fillStyle; + ctx.strokeStyle = "rgba(130, 130, 130, 0.8)"; + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + + var startAngle = - Math.PI / 2; + var currentAngle = startAngle; + var memoryBlock = this._memorySnapshot; + + function paintPercentAndLabel(fraction, title, midAngle) + { + ctx.beginPath(); + ctx.font = "14px Arial"; + ctx.fillStyle = "rgba(10, 10, 10, 0.8)"; + + var textX = x + radius * Math.cos(midAngle) / 2; + var textY = y + radius * Math.sin(midAngle) / 2; + ctx.fillText((100 * fraction).toFixed(0) + "%", textX, textY); + + textX = x + radius * Math.cos(midAngle); + textY = y + radius * Math.sin(midAngle); + if (midAngle <= startAngle + Math.PI) { + textX += 10; + textY += 10; + } else { + var metrics = ctx.measureText(title); + textX -= metrics.width + 10; + } + ctx.fillText(title, textX, textY); + ctx.closePath(); + } + + if (memoryBlock.children) { + var total = memoryBlock.size; + for (var i = 0; i < memoryBlock.children.length; i++) { + var child = memoryBlock.children[i]; + if (!child.size) + continue; + var viewProperties = WebInspector.MemoryBlockViewProperties._forMemoryBlock(child); + var angleSpan = Math.PI * 2 * (child.size / total); + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(x + radius * Math.cos(currentAngle), y + radius * Math.sin(currentAngle)); + ctx.arc(x, y, radius, currentAngle, currentAngle + angleSpan, false); + ctx.lineWidth = 0.5; + ctx.lineTo(x, y); + ctx.fillStyle = viewProperties._fillStyle; + ctx.strokeStyle = "rgba(100, 100, 100, 0.8)"; + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + + paintPercentAndLabel(child.size / total, viewProperties._description, currentAngle + angleSpan / 2); + + currentAngle += angleSpan; + } + } + + var fraction = 1 - (currentAngle - startAngle) / (2 * Math.PI); + var midAngle = (currentAngle + startAngle + 2 * Math.PI) / 2; + paintPercentAndLabel(fraction, WebInspector.UIString("Unknown"), midAngle); + }, + + _clear: function() { + var ctx = this._canvas.getContext("2d"); + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + } +} + +WebInspector.NativeMemoryPieChart.prototype.__proto__ = WebInspector.View.prototype; |