diff options
Diffstat (limited to 'WebCore/inspector/front-end/TimelineOverviewPane.js')
-rw-r--r-- | WebCore/inspector/front-end/TimelineOverviewPane.js | 251 |
1 files changed, 176 insertions, 75 deletions
diff --git a/WebCore/inspector/front-end/TimelineOverviewPane.js b/WebCore/inspector/front-end/TimelineOverviewPane.js index 09431dc..3e83f62 100644 --- a/WebCore/inspector/front-end/TimelineOverviewPane.js +++ b/WebCore/inspector/front-end/TimelineOverviewPane.js @@ -30,32 +30,26 @@ WebInspector.TimelineOverviewPane = function(categories) { - this.element = document.createElement("div"); - this.element.id = "timeline-overview-panel"; - this._categories = categories; - this._overviewSidebarElement = document.createElement("div"); - this._overviewSidebarElement.id = "timeline-overview-sidebar"; - this.element.appendChild(this._overviewSidebarElement); - - var overviewTreeElement = document.createElement("ol"); - overviewTreeElement.className = "sidebar-tree"; - this._overviewSidebarElement.appendChild(overviewTreeElement); - var sidebarTree = new TreeOutline(overviewTreeElement); - - var categoriesTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("TIMELINES"), {}, true); - categoriesTreeElement.expanded = true; - sidebarTree.appendChild(categoriesTreeElement); + + this.statusBarFilters = document.createElement("div"); + this.statusBarFilters.id = "timeline-view-status-bar-items"; + this.statusBarFilters.addStyleClass("status-bar-item"); for (var categoryName in this._categories) { var category = this._categories[categoryName]; - categoriesTreeElement.appendChild(new WebInspector.TimelineCategoryTreeElement(category, this._onCheckboxClicked.bind(this, category))); + this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCheckboxClicked.bind(this, category))); } this._overviewGrid = new WebInspector.TimelineGrid(); this._overviewGrid.element.id = "timeline-overview-grid"; - this._overviewGrid.itemsGraphsElement.id = "timeline-overview-graphs"; + this._overviewGrid.itemsGraphsElement.id = "timeline-overview-timelines"; this._overviewGrid.element.addEventListener("mousedown", this._dragWindow.bind(this), true); - this.element.appendChild(this._overviewGrid.element); + + this._heapGraph = new WebInspector.HeapGraph(); + this._heapGraph.element.id = "timeline-overview-memory"; + this._overviewGrid.element.insertBefore(this._heapGraph.element, this._overviewGrid.itemsGraphsElement); + + this.element = this._overviewGrid.element; this._categoryGraphs = {}; var i = 0; @@ -90,10 +84,6 @@ WebInspector.TimelineOverviewPane = function(categories) this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); - var separatorElement = document.createElement("div"); - separatorElement.id = "timeline-overview-separator"; - this.element.appendChild(separatorElement); - this.windowLeft = 0.0; this.windowRight = 1.0; } @@ -101,6 +91,17 @@ WebInspector.TimelineOverviewPane = function(categories) WebInspector.TimelineOverviewPane.minSelectableSize = 12; WebInspector.TimelineOverviewPane.prototype = { + showTimelines: function(event) { + this._heapGraph.hide(); + this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden"); + }, + + showMemoryGraph: function(records) { + this._heapGraph.show(); + this._heapGraph.update(records); + this._overviewGrid.itemsGraphsElement.addStyleClass("hidden"); + }, + _onCheckboxClicked: function (category, event) { if (event.target.checked) category.hidden = false; @@ -110,6 +111,16 @@ WebInspector.TimelineOverviewPane.prototype = { this.dispatchEventToListeners("filter changed"); }, + _forAllRecords: function(recordsArray, callback) + { + if (!recordsArray) + return; + for (var i = 0; i < recordsArray.length; ++i) { + callback(recordsArray[i]); + this._forAllRecords(recordsArray[i].children, callback); + } + }, + update: function(records, showShortEvents) { this._showShortEvents = showShortEvents; @@ -120,19 +131,9 @@ WebInspector.TimelineOverviewPane.prototype = { this._categoryGraphs[category].clearChunks(); } - function forAllRecords(recordsArray, callback) - { - if (!recordsArray) - return; - for (var i = 0; i < recordsArray.length; ++i) { - callback(recordsArray[i]); - forAllRecords(recordsArray[i].children, callback); - } - } - // Create sparse arrays with 101 cells each to fill with chunks for a given category. this._overviewCalculator.reset(); - forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator)); + this._forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator)); function markTimeline(record) { @@ -145,7 +146,7 @@ WebInspector.TimelineOverviewPane.prototype = { for (var j = Math.round(percentages.start); j <= end; ++j) timelines[categoryName][j] = true; } - forAllRecords(records, markTimeline.bind(this)); + this._forAllRecords(records, markTimeline.bind(this)); // Convert sparse arrays to continuous segments, render graphs for each. for (var category in this._categories) { @@ -168,6 +169,11 @@ WebInspector.TimelineOverviewPane.prototype = { chunkStart = -1; } } + + this._heapGraph.setSize(this._overviewGrid.element.offsetWidth, 60); + if (this._heapGraph.visible) + this._heapGraph.update(records); + this._overviewGrid.updateDividers(true, this._overviewCalculator); }, @@ -188,12 +194,7 @@ WebInspector.TimelineOverviewPane.prototype = { this._overviewGrid.addEventDividers(dividers); }, - setSidebarWidth: function(width) - { - this._overviewSidebarElement.style.width = width + "px"; - }, - - updateMainViewWidth: function(width) + updateMainViewWidth: function(width, records) { this._overviewGrid.element.style.left = width + "px"; }, @@ -328,7 +329,32 @@ WebInspector.TimelineOverviewPane.prototype = { _endWindowDragging: function(event) { WebInspector.elementDragEnd(event); + }, + + _createTimelineCategoryStatusBarCheckbox: function(category, onCheckboxClicked) + { + var labelContainer = document.createElement("div"); + labelContainer.addStyleClass("timeline-category-statusbar-item"); + labelContainer.addStyleClass("timeline-category-" + category.name); + labelContainer.addStyleClass("status-bar-item"); + + var label = document.createElement("label"); + var checkElement = document.createElement("input"); + checkElement.type = "checkbox"; + checkElement.className = "timeline-category-checkbox"; + checkElement.checked = true; + checkElement.addEventListener("click", onCheckboxClicked); + label.appendChild(checkElement); + + var typeElement = document.createElement("span"); + typeElement.className = "type"; + typeElement.textContent = category.title; + label.appendChild(typeElement); + + labelContainer.appendChild(label); + return labelContainer; } + } WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.Object.prototype; @@ -377,41 +403,6 @@ WebInspector.TimelineOverviewCalculator.prototype = { } -WebInspector.TimelineCategoryTreeElement = function(category, onCheckboxClicked) -{ - this._category = category; - this._onCheckboxClicked = onCheckboxClicked; - // Pass an empty title, the title gets made later in onattach. - TreeElement.call(this, "", null, false); -} - -WebInspector.TimelineCategoryTreeElement.prototype = { - onattach: function() - { - this.listItemElement.removeChildren(); - this.listItemElement.addStyleClass("timeline-category-tree-item"); - this.listItemElement.addStyleClass("timeline-category-" + this._category.name); - - var label = document.createElement("label"); - - var checkElement = document.createElement("input"); - checkElement.type = "checkbox"; - checkElement.className = "timeline-category-checkbox"; - checkElement.checked = true; - checkElement.addEventListener("click", this._onCheckboxClicked); - label.appendChild(checkElement); - - var typeElement = document.createElement("span"); - typeElement.className = "type"; - typeElement.textContent = this._category.title; - label.appendChild(typeElement); - - this.listItemElement.appendChild(label); - } -} - -WebInspector.TimelineCategoryTreeElement.prototype.__proto__ = TreeElement.prototype; - WebInspector.TimelineCategoryGraph = function(category, isEven) { this._category = category; @@ -497,3 +488,113 @@ WebInspector.TimelinePanel.WindowSelector.prototype = { } } +WebInspector.HeapGraph = function() { + this._canvas = document.createElement("canvas"); + + this._maxHeapSizeLabel = document.createElement("div"); + this._maxHeapSizeLabel.addStyleClass("memory-graph-label"); + + this._element = document.createElement("div"); + this._element.addStyleClass("hidden"); + this._element.appendChild(this._canvas); + this._element.appendChild(this._maxHeapSizeLabel); +} + +WebInspector.HeapGraph.prototype = { + get element() { + // return this._canvas; + return this._element; + }, + + get visible() { + return !this.element.hasStyleClass("hidden"); + }, + + show: function() { + this.element.removeStyleClass("hidden"); + }, + + hide: function() { + this.element.addStyleClass("hidden"); + }, + + setSize: function(w, h) { + this._canvas.width = w; + this._canvas.height = h - 5; + }, + + update: function(records) + { + if (!records.length) + return; + + var maxTotalHeapSize = 0; + var minTime; + var maxTime; + this._forAllRecords(records, function(r) { + if (r.totalHeapSize && r.totalHeapSize > maxTotalHeapSize) + maxTotalHeapSize = r.totalHeapSize; + + if (typeof minTime === "undefined" || r.startTime < minTime) + minTime = r.startTime; + if (typeof maxTime === "undefined" || r.endTime > maxTime) + maxTime = r.endTime; + }); + + var width = this._canvas.width; + var height = this._canvas.height; + var xFactor = width / (maxTime - minTime); + var yFactor = height / maxTotalHeapSize; + + var histogram = new Array(width); + this._forAllRecords(records, function(r) { + if (!r.usedHeapSize) + return; + var x = Math.round((r.endTime - minTime) * xFactor); + var y = Math.round(r.usedHeapSize * yFactor); + histogram[x] = Math.max(histogram[x] || 0, y); + }); + + var ctx = this._canvas.getContext("2d"); + this._clear(ctx); + + // +1 so that the border always fit into the canvas area. + height = height + 1; + + ctx.beginPath(); + var initialY = 0; + for (var k = 0; k < histogram.length; k++) { + if (histogram[k]) { + initialY = histogram[k]; + break; + } + } + ctx.moveTo(0, height - initialY); + + for (var x = 0; x < histogram.length; x++) { + if (!histogram[x]) + continue; + ctx.lineTo(x, height - histogram[x]); + } + + ctx.lineWidth = 0.5; + ctx.strokeStyle = "rgba(20,0,0,0.8)"; + ctx.stroke(); + + ctx.fillStyle = "rgba(214,225,254, 0.8);"; + ctx.lineTo(width, 60); + ctx.lineTo(0, 60); + ctx.lineTo(0, height - initialY); + ctx.fill(); + ctx.closePath(); + + this._maxHeapSizeLabel.textContent = Number.bytesToString(maxTotalHeapSize); + }, + + _clear: function(ctx) { + ctx.fillStyle = "rgba(255,255,255,0.8)"; + ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + }, + + _forAllRecords: WebInspector.TimelineOverviewPane.prototype._forAllRecords +} |