1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /** 32 * @constructor 33 * @extends {WebInspector.TimelineOverviewBase} 34 * @param {!WebInspector.TimelineModel} model 35 * @param {!WebInspector.TimelineUIUtils} uiUtils 36 */ 37 WebInspector.TimelineMemoryOverview = function(model, uiUtils) 38 { 39 WebInspector.TimelineOverviewBase.call(this, model); 40 this._uiUtils = uiUtils; 41 this.element.id = "timeline-overview-memory"; 42 43 this._heapSizeLabel = this.element.createChild("div", "memory-graph-label"); 44 } 45 46 WebInspector.TimelineMemoryOverview.prototype = { 47 resetHeapSizeLabels: function() 48 { 49 this._heapSizeLabel.textContent = ""; 50 }, 51 52 update: function() 53 { 54 this.resetCanvas(); 55 var ratio = window.devicePixelRatio; 56 57 var records = this._model.records(); 58 if (!records.length) { 59 this.resetHeapSizeLabels(); 60 return; 61 } 62 63 var lowerOffset = 3 * ratio; 64 var maxUsedHeapSize = 0; 65 var minUsedHeapSize = 100000000000; 66 var minTime = this._model.minimumRecordTime(); 67 var maxTime = this._model.maximumRecordTime(); 68 var uiUtils = this._uiUtils; 69 /** 70 * @param {!WebInspector.TimelineModel.Record} record 71 */ 72 function calculateMinMaxSizes(record) 73 { 74 var counters = uiUtils.countersForRecord(record); 75 if (!counters || !counters.jsHeapSizeUsed) 76 return; 77 maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed); 78 minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed); 79 } 80 this._model.forAllRecords(calculateMinMaxSizes); 81 minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize); 82 83 var lineWidth = 1; 84 var width = this._canvas.width; 85 var height = this._canvas.height - lowerOffset; 86 var xFactor = width / (maxTime - minTime); 87 var yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1); 88 89 var histogram = new Array(width); 90 91 /** 92 * @param {!WebInspector.TimelineModel.Record} record 93 */ 94 function buildHistogram(record) 95 { 96 var counters = uiUtils.countersForRecord(record); 97 if (!counters || !counters.jsHeapSizeUsed) 98 return; 99 var x = Math.round((record.endTime() - minTime) * xFactor); 100 var y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor); 101 histogram[x] = Math.max(histogram[x] || 0, y); 102 } 103 this._model.forAllRecords(buildHistogram); 104 105 var ctx = this._context; 106 var heightBeyondView = height + lowerOffset + lineWidth; 107 108 ctx.translate(0.5, 0.5); 109 ctx.beginPath(); 110 ctx.moveTo(-lineWidth, heightBeyondView); 111 var y = 0; 112 var isFirstPoint = true; 113 var lastX = 0; 114 for (var x = 0; x < histogram.length; x++) { 115 if (typeof histogram[x] === "undefined") 116 continue; 117 if (isFirstPoint) { 118 isFirstPoint = false; 119 y = histogram[x]; 120 ctx.lineTo(-lineWidth, height - y); 121 } 122 var nextY = histogram[x]; 123 if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1) 124 ctx.lineTo(x, height - y); 125 y = nextY; 126 ctx.lineTo(x, height - y); 127 lastX = x; 128 } 129 ctx.lineTo(width + lineWidth, height - y); 130 ctx.lineTo(width + lineWidth, heightBeyondView); 131 ctx.closePath(); 132 133 ctx.fillStyle = "hsla(220, 90%, 70%, 0.2)"; 134 ctx.fill(); 135 ctx.lineWidth = lineWidth; 136 ctx.strokeStyle = "hsl(220, 90%, 70%)"; 137 ctx.stroke(); 138 139 this._heapSizeLabel.textContent = WebInspector.UIString("%s \u2013 %s", Number.bytesToString(minUsedHeapSize), Number.bytesToString(maxUsedHeapSize)); 140 }, 141 142 __proto__: WebInspector.TimelineOverviewBase.prototype 143 } 144