Chromium Code Reviews| Index: Source/devtools/front_end/timeline/TimelineEventOverview.js |
| diff --git a/Source/devtools/front_end/timeline/TimelineEventOverview.js b/Source/devtools/front_end/timeline/TimelineEventOverview.js |
| index d797d751b6a0c2223af095b6a1c672d84c697ab9..5c94924ee2a5dea424c131c1dea19070426c2a43 100644 |
| --- a/Source/devtools/front_end/timeline/TimelineEventOverview.js |
| +++ b/Source/devtools/front_end/timeline/TimelineEventOverview.js |
| @@ -51,7 +51,7 @@ WebInspector.TimelineEventOverview = function(model, frameModel) |
| } |
| /** @const */ |
| -WebInspector.TimelineEventOverview._fullStripHeight = 16; |
| +WebInspector.TimelineEventOverview._fullStripHeight = 20; |
| /** @const */ |
| WebInspector.TimelineEventOverview._smallStripHeight = 8; |
| @@ -89,7 +89,7 @@ WebInspector.TimelineEventOverview.prototype = { |
| position += this._drawNetwork(mainThreadEvents, position, networkHeight); |
| if (Runtime.experiments.isEnabled("frameRateOnEventsOverview")) |
| position += this._drawFrames(position, WebInspector.TimelineEventOverview._fullStripHeight); |
| - position += this._drawEvents(mainThreadEvents, position, WebInspector.TimelineEventOverview._fullStripHeight); |
| + position += this._drawStackedUtilizationChart(mainThreadEvents, position, WebInspector.TimelineEventOverview._fullStripHeight); |
| for (var thread of threads.filter(function(thread) { return !thread.isWorker(); })) |
| this._drawEvents(thread.events, position, WebInspector.TimelineEventOverview._smallStripHeight); |
| position += WebInspector.TimelineEventOverview._smallStripHeight; |
| @@ -189,6 +189,73 @@ WebInspector.TimelineEventOverview.prototype = { |
| /** |
| * @param {!Array.<!WebInspector.TracingModel.Event>} events |
| * @param {number} position |
| + * @param {number} height |
| + * @return {number} |
| + */ |
| + _drawStackedUtilizationChart: function(events, position, height) |
| + { |
| + var /** @const */ quantSizePx = 4 * window.devicePixelRatio; |
| + var /** @const */ padding = 1; |
| + var visualHeight = (height - padding) * window.devicePixelRatio; |
| + var baseLine = (position + height) * window.devicePixelRatio; |
| + var timeOffset = this._model.minimumRecordTime(); |
| + var timeSpan = this._model.maximumRecordTime() - timeOffset; |
| + var scale = this._canvas.width / timeSpan; |
| + var quantTime = quantSizePx / scale; |
| + var quantizer = new WebInspector.Quantizer(timeOffset, quantTime, drawSample.bind(this)); |
| + var ctx = this._context; |
| + var x = 0; |
| + var categories = WebInspector.TimelineUIUtils.categories(); |
| + var categoryOrder = ["idle", "scripting", "rendering", "painting", "loading", "other"]; |
| + var idleIndex = categoryOrder.indexOf("idle"); |
|
yurys
2015/06/09 09:19:26
idleIndex = 0 and assert?
alph
2015/06/09 09:47:24
Done.
|
| + var otherIndex = categoryOrder.indexOf("other"); |
| + for (var i = 1; i < categoryOrder.length; ++i) |
| + categories[categoryOrder[i]]._overviewIndex = i; |
|
yurys
2015/06/09 09:19:26
Consider doing this once in the categories initial
alph
2015/06/09 09:47:24
The index is specific to this function, so I want
|
| + var indexStack = []; |
| + |
| + /** |
| + * @param {!Array<number>} counters |
| + * @this {WebInspector.TimelineEventOverview} |
| + */ |
| + function drawSample(counters) |
| + { |
| + var y = baseLine; |
| + for (var i = idleIndex + 1; i < counters.length; ++i) { |
| + if (!counters[i]) |
| + continue; |
| + var h = counters[i] / quantTime * visualHeight; |
| + ctx.fillStyle = this._categoryColor(categories[categoryOrder[i]]); |
| + ctx.fillRect(x, y - h, quantSizePx, h); |
| + y -= h; |
| + } |
| + x += quantSizePx; |
| + } |
| + |
| + /** |
| + * @param {!WebInspector.TracingModel.Event} e |
| + */ |
| + function onEventStart(e) |
| + { |
| + var index = indexStack.length ? indexStack.peekLast() : idleIndex; |
|
yurys
2015/06/09 09:19:26
categoryIndexStack?
alph
2015/06/09 09:47:24
Done.
|
| + quantizer.appendInterval(e.startTime, index); |
| + indexStack.push(WebInspector.TimelineUIUtils.eventStyle(e).category._overviewIndex || otherIndex); |
| + } |
| + |
| + /** |
| + * @param {!WebInspector.TracingModel.Event} e |
| + */ |
| + function onEventEnd(e) |
| + { |
| + quantizer.appendInterval(e.endTime, indexStack.pop()); |
| + } |
| + |
| + WebInspector.TimelineModel.forEachEvent(events, onEventStart, onEventEnd); |
| + return height; |
| + }, |
| + |
| + /** |
| + * @param {!Array.<!WebInspector.TracingModel.Event>} events |
| + * @param {number} position |
| * @param {number} stripHeight |
| * @return {number} |
| */ |
| @@ -205,16 +272,6 @@ WebInspector.TimelineEventOverview.prototype = { |
| position += padding; |
| /** |
| - * @param {!WebInspector.TimelineCategory} category |
| - * @return {string} |
| - * @this {WebInspector.TimelineEventOverview} |
| - */ |
| - function categoryColor(category) |
| - { |
| - return category.hidden ? this._disabledCategoryFillStyle : this._fillStyles[category.name]; |
| - } |
| - |
| - /** |
| * @param {!WebInspector.TracingModel.Event} e |
| * @this {WebInspector.TimelineEventOverview} |
| */ |
| @@ -225,7 +282,7 @@ WebInspector.TimelineEventOverview.prototype = { |
| var category = categoryStack.peekLast(); |
| var bar = ditherer.appendInterval(category, lastX, pos); |
| if (bar) |
| - this._renderBar(bar.start, bar.end, position, visualHeight, categoryColor.call(this, category)); |
| + this._renderBar(bar.start, bar.end, position, visualHeight, this._categoryColor(category)); |
| } |
| categoryStack.push(WebInspector.TimelineUIUtils.eventStyle(e).category); |
| lastX = pos; |
| @@ -241,7 +298,7 @@ WebInspector.TimelineEventOverview.prototype = { |
| var pos = (e.endTime - timeOffset) * scale; |
| var bar = ditherer.appendInterval(category, lastX, pos); |
| if (bar) |
| - this._renderBar(bar.start, bar.end, position, visualHeight, categoryColor.call(this, category)); |
| + this._renderBar(bar.start, bar.end, position, visualHeight, this._categoryColor(category)); |
| lastX = pos; |
| } |
| @@ -250,6 +307,15 @@ WebInspector.TimelineEventOverview.prototype = { |
| }, |
| /** |
| + * @param {!WebInspector.TimelineCategory} category |
| + * @return {string} |
| + */ |
| + _categoryColor: function(category) |
| + { |
| + return category.hidden ? this._disabledCategoryFillStyle : this._fillStyles[category.name]; |
| + }, |
| + |
| + /** |
| * @param {number} position |
| * @param {number} height |
| * @return {number} |
| @@ -392,3 +458,48 @@ WebInspector.Dithering.prototype = { |
| return toDistribute; |
| } |
| } |
| + |
| +/** |
| + * @constructor |
| + * @param {number} startTime |
| + * @param {number} quantDuration |
| + * @param {function(!Array<number>)} callback |
| + */ |
| +WebInspector.Quantizer = function(startTime, quantDuration, callback) |
| +{ |
| + this._lastTime = startTime; |
| + this._quantDuration = quantDuration; |
| + this._callback = callback; |
| + this._counters = []; |
| + this._remainder = 0; |
| +} |
| + |
| +WebInspector.Quantizer.prototype = { |
| + /** |
| + * @param {number} time |
| + * @param {number} group |
| + */ |
| + appendInterval: function(time, group) |
| + { |
| + var interval = time - this._lastTime; |
| + if (this._remainder + interval < this._quantDuration) { |
| + this._counters[group] = (this._counters[group] || 0) + interval; |
| + this._remainder += interval; |
|
yurys
2015/06/09 09:19:26
_remainder -> _elapsed or _utilized ? Or better ma
alph
2015/06/09 09:47:24
Done.
|
| + this._lastTime = time; |
| + return; |
| + } |
| + this._counters[group] = (this._counters[group] || 0) + this._quantDuration - this._remainder; |
| + this._callback(this._counters); |
| + interval -= this._quantDuration - this._remainder; |
| + while (interval >= this._quantDuration) { |
| + var counters = []; |
| + counters[group] = this._quantDuration; |
| + this._callback(counters); |
| + interval -= this._quantDuration; |
| + } |
| + this._counters = []; |
| + this._counters[group] = interval; |
| + this._lastTime = time; |
| + this._remainder = interval; |
| + } |
| +} |