OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 13 matching lines...) Expand all Loading... | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 /** | 31 /** |
32 * @constructor | 32 * @constructor |
33 * @extends {WebInspector.TimelineOverviewBase} | 33 * @extends {WebInspector.TimelineOverviewBase} |
34 * @param {string} id | |
caseq
2015/06/26 15:53:47
nit: id -> class or name?
alph
2015/06/26 16:11:19
it's in fact part of id, not the class. so let me
| |
34 * @param {!WebInspector.TimelineModel} model | 35 * @param {!WebInspector.TimelineModel} model |
35 * @param {!WebInspector.TimelineFrameModelBase} frameModel | |
36 */ | 36 */ |
37 WebInspector.TimelineEventOverview = function(model, frameModel) | 37 WebInspector.TimelineEventOverview = function(id, model) |
38 { | 38 { |
39 WebInspector.TimelineOverviewBase.call(this); | 39 WebInspector.TimelineOverviewBase.call(this); |
40 this.element.id = "timeline-overview-events"; | 40 this.element.id = "timeline-overview-" + id; |
41 this.element.classList.add("overview-strip"); | |
41 this._model = model; | 42 this._model = model; |
42 this._frameModel = frameModel; | |
43 | |
44 this._fillStyles = {}; | |
45 var categories = WebInspector.TimelineUIUtils.categories(); | |
46 for (var category in categories) { | |
47 this._fillStyles[category] = categories[category].fillColorStop1; | |
48 categories[category].addEventListener(WebInspector.TimelineCategory.Even ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); | |
49 } | |
50 | |
51 this._disabledCategoryFillStyle = "hsl(0, 0%, 67%)"; | |
52 } | 43 } |
53 | 44 |
54 /** @const */ | |
55 WebInspector.TimelineEventOverview._fullStripHeight = 24; | |
56 /** @const */ | |
57 WebInspector.TimelineEventOverview._smallStripHeight = 8; | |
58 | |
59 WebInspector.TimelineEventOverview.prototype = { | 45 WebInspector.TimelineEventOverview.prototype = { |
60 /** | 46 /** |
61 * @override | 47 * @param {number} y |
48 * @param {string} label | |
62 */ | 49 */ |
63 dispose: function() | 50 _drawHorizontalGuide: function(y, label) |
64 { | 51 { |
65 WebInspector.TimelineOverviewBase.prototype.dispose.call(this); | 52 var ctx = this._context; |
66 var categories = WebInspector.TimelineUIUtils.categories(); | 53 ctx.save(); |
67 for (var category in categories) | 54 ctx.translate(0, y); |
68 categories[category].removeEventListener(WebInspector.TimelineCatego ry.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this); | 55 ctx.scale(window.devicePixelRatio, window.devicePixelRatio); |
56 ctx.beginPath(); | |
57 ctx.moveTo(0, 0); | |
58 ctx.lineTo(this._canvas.width, 0); | |
59 ctx.strokeStyle = "hsl(0, 0%, 85%)"; | |
60 ctx.setLineDash([3]); | |
61 ctx.lineWidth = 1; | |
62 ctx.stroke(); | |
63 ctx.fillStyle = "hsl(0, 0%, 60%)"; | |
64 ctx.font = "9px " + WebInspector.fontFamily(); | |
65 ctx.fillText(label, 5, 9); | |
66 ctx.restore(); | |
69 }, | 67 }, |
70 | 68 |
71 /** | 69 /** |
70 * @param {number} begin | |
71 * @param {number} end | |
72 * @param {number} position | |
73 * @param {number} height | |
74 * @param {string} color | |
75 */ | |
76 _renderBar: function(begin, end, position, height, color) | |
77 { | |
78 var x = begin; | |
79 var width = end - begin; | |
80 this._context.fillStyle = color; | |
81 this._context.fillRect(x, position, width, height); | |
82 }, | |
83 | |
84 /** | |
85 * @override | |
86 * @param {number} windowLeft | |
87 * @param {number} windowRight | |
88 * @return {!{startTime: number, endTime: number}} | |
89 */ | |
90 windowTimes: function(windowLeft, windowRight) | |
91 { | |
92 var absoluteMin = this._model.minimumRecordTime(); | |
93 var timeSpan = this._model.maximumRecordTime() - absoluteMin; | |
94 return { | |
95 startTime: absoluteMin + timeSpan * windowLeft, | |
96 endTime: absoluteMin + timeSpan * windowRight | |
97 }; | |
98 }, | |
99 | |
100 /** | |
101 * @override | |
102 * @param {number} startTime | |
103 * @param {number} endTime | |
104 * @return {!{left: number, right: number}} | |
105 */ | |
106 windowBoundaries: function(startTime, endTime) | |
107 { | |
108 var absoluteMin = this._model.minimumRecordTime(); | |
109 var timeSpan = this._model.maximumRecordTime() - absoluteMin; | |
110 var haveRecords = absoluteMin > 0; | |
111 return { | |
112 left: haveRecords && startTime ? Math.min((startTime - absoluteMin) / timeSpan, 1) : 0, | |
113 right: haveRecords && endTime < Infinity ? (endTime - absoluteMin) / timeSpan : 1 | |
114 }; | |
115 }, | |
116 | |
117 __proto__: WebInspector.TimelineOverviewBase.prototype | |
118 } | |
119 | |
120 /** | |
121 * @constructor | |
122 * @extends {WebInspector.TimelineEventOverview} | |
123 * @param {!WebInspector.TimelineModel} model | |
124 */ | |
125 WebInspector.TimelineEventOverview.Input = function(model) | |
126 { | |
127 WebInspector.TimelineEventOverview.call(this, "input", model); | |
128 } | |
129 | |
130 WebInspector.TimelineEventOverview.Input.prototype = { | |
131 /** | |
72 * @override | 132 * @override |
73 */ | 133 */ |
74 update: function() | 134 update: function() |
75 { | 135 { |
76 var /** @const */ fpsStripHeight = 20; | |
77 this.resetCanvas(); | 136 this.resetCanvas(); |
78 var threads = this._model.virtualThreads(); | 137 var events = this._model.mainThreadEvents(); |
79 var mainThreadEvents = this._model.mainThreadEvents(); | 138 var height = this._canvas.height; |
80 var networkHeight = this._canvas.clientHeight | |
81 - WebInspector.TimelineEventOverview._fullStripHeight | |
82 - fpsStripHeight | |
83 - 3 * WebInspector.TimelineEventOverview._smallStripHeight; | |
84 var position = 0; | |
85 if (Runtime.experiments.isEnabled("inputEventsOnTimelineOverview")) { | |
86 var inputHeight = this._drawInputEvents(mainThreadEvents, position, WebInspector.TimelineEventOverview._smallStripHeight); | |
87 position += inputHeight; | |
88 networkHeight -= inputHeight; | |
89 } | |
90 position += this._drawNetwork(mainThreadEvents, position, networkHeight) ; | |
91 position += this._drawStackedUtilizationChart(mainThreadEvents, position , WebInspector.TimelineEventOverview._fullStripHeight); | |
92 for (var thread of threads.filter(function(thread) { return !thread.isWo rker(); })) | |
93 this._drawEvents(thread.events, position, WebInspector.TimelineEvent Overview._smallStripHeight); | |
94 position += WebInspector.TimelineEventOverview._smallStripHeight; | |
95 for (var thread of threads.filter(function(thread) { return thread.isWor ker(); })) | |
96 this._drawEvents(thread.events, position, WebInspector.TimelineEvent Overview._smallStripHeight); | |
97 position += WebInspector.TimelineEventOverview._smallStripHeight; | |
98 position += this._drawResponsivenessStrip(position, WebInspector.Timelin eEventOverview._smallStripHeight); | |
99 position += this._drawFrames(position, fpsStripHeight); | |
100 console.assert(position === this._canvas.clientHeight); | |
101 }, | |
102 | |
103 /** | |
104 * @param {!Array.<!WebInspector.TracingModel.Event>} events | |
105 * @param {number} position | |
106 * @param {number} height | |
107 * @return {number} | |
108 */ | |
109 _drawInputEvents: function(events, position, height) | |
110 { | |
111 var /** @const */ padding = 1; | |
112 var descriptors = WebInspector.TimelineUIUtils.eventDispatchDesciptors() ; | 139 var descriptors = WebInspector.TimelineUIUtils.eventDispatchDesciptors() ; |
113 /** @type {!Map.<string,!WebInspector.TimelineUIUtils.EventDispatchTypeD escriptor>} */ | 140 /** @type {!Map.<string,!WebInspector.TimelineUIUtils.EventDispatchTypeD escriptor>} */ |
114 var descriptorsByType = new Map(); | 141 var descriptorsByType = new Map(); |
115 var maxPriority = -1; | 142 var maxPriority = -1; |
116 for (var descriptor of descriptors) { | 143 for (var descriptor of descriptors) { |
117 for (var type of descriptor.eventTypes) | 144 for (var type of descriptor.eventTypes) |
118 descriptorsByType.set(type, descriptor); | 145 descriptorsByType.set(type, descriptor); |
119 maxPriority = Math.max(maxPriority, descriptor.priority); | 146 maxPriority = Math.max(maxPriority, descriptor.priority); |
120 } | 147 } |
121 | 148 |
122 var devicePixelRatio = window.devicePixelRatio; | 149 var /** @const */ minWidth = 2 * window.devicePixelRatio; |
123 var /** @const */ minWidth = 2 * devicePixelRatio; | |
124 var stripHeight = (height - padding) * devicePixelRatio; | |
125 var timeOffset = this._model.minimumRecordTime(); | 150 var timeOffset = this._model.minimumRecordTime(); |
126 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 151 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
127 var canvasWidth = this._canvas.width; | 152 var canvasWidth = this._canvas.width; |
128 var scale = canvasWidth / timeSpan; | 153 var scale = canvasWidth / timeSpan; |
129 position = (position + padding) * devicePixelRatio; | |
130 | 154 |
131 for (var priority = 0; priority <= maxPriority; ++priority) { | 155 for (var priority = 0; priority <= maxPriority; ++priority) { |
132 for (var i = 0; i < events.length; ++i) { | 156 for (var i = 0; i < events.length; ++i) { |
133 var event = events[i]; | 157 var event = events[i]; |
134 if (event.name !== WebInspector.TimelineModel.RecordType.EventDi spatch) | 158 if (event.name !== WebInspector.TimelineModel.RecordType.EventDi spatch) |
135 continue; | 159 continue; |
136 var descriptor = descriptorsByType.get(event.args["data"]["type" ]); | 160 var descriptor = descriptorsByType.get(event.args["data"]["type" ]); |
137 if (!descriptor || descriptor.priority !== priority) | 161 if (!descriptor || descriptor.priority !== priority) |
138 continue; | 162 continue; |
139 var start = Number.constrain(Math.floor((event.startTime - timeO ffset) * scale), 0, canvasWidth); | 163 var start = Number.constrain(Math.floor((event.startTime - timeO ffset) * scale), 0, canvasWidth); |
140 var end = Number.constrain(Math.ceil((event.endTime - timeOffset ) * scale), 0, canvasWidth); | 164 var end = Number.constrain(Math.ceil((event.endTime - timeOffset ) * scale), 0, canvasWidth); |
141 var width = Math.max(end - start, minWidth); | 165 var width = Math.max(end - start, minWidth); |
142 this._renderBar(start, start + width, position, stripHeight, des criptor.color); | 166 this._renderBar(start, start + width, 0, height, descriptor.colo r); |
143 } | 167 } |
144 } | 168 } |
145 | |
146 return height; | |
147 }, | 169 }, |
148 | 170 |
171 __proto__: WebInspector.TimelineEventOverview.prototype | |
172 } | |
173 | |
174 /** | |
175 * @constructor | |
176 * @extends {WebInspector.TimelineEventOverview} | |
177 * @param {!WebInspector.TimelineModel} model | |
178 */ | |
179 WebInspector.TimelineEventOverview.Network = function(model) | |
180 { | |
181 WebInspector.TimelineEventOverview.call(this, "network", model); | |
182 } | |
183 | |
184 WebInspector.TimelineEventOverview.Network.prototype = { | |
149 /** | 185 /** |
150 * @param {!Array.<!WebInspector.TracingModel.Event>} events | 186 * @override |
151 * @param {number} position | |
152 * @param {number} height | |
153 * @return {number} | |
154 */ | 187 */ |
155 _drawNetwork: function(events, position, height) | 188 update: function() |
156 { | 189 { |
157 var /** @const */ padding = 1; | 190 this.resetCanvas(); |
158 var /** @const */ maxBandHeight = 4; | 191 var events = this._model.mainThreadEvents(); |
159 position += padding; | 192 var height = this._canvas.height; |
160 var devicePixelRatio = window.devicePixelRatio; | 193 var /** @const */ maxBandHeight = 4 * window.devicePixelRatio; |
161 var bandsCount = WebInspector.TimelineUIUtils.calculateNetworkBandsCount (events); | 194 var bandsCount = WebInspector.TimelineUIUtils.calculateNetworkBandsCount (events); |
162 var bandInterval = Math.min(maxBandHeight, (height - padding) / (bandsCo unt || 1)); | 195 var bandInterval = Math.min(maxBandHeight, height / (bandsCount || 1)); |
163 var bandHeight = Math.ceil(bandInterval * devicePixelRatio); | 196 var bandHeight = Math.ceil(bandInterval); |
164 var timeOffset = this._model.minimumRecordTime(); | 197 var timeOffset = this._model.minimumRecordTime(); |
165 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 198 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
166 var canvasWidth = this._canvas.width; | 199 var canvasWidth = this._canvas.width; |
167 var scale = canvasWidth / timeSpan; | 200 var scale = canvasWidth / timeSpan; |
168 var loadingCategory = WebInspector.TimelineUIUtils.categories()["loading "]; | 201 var loadingCategory = WebInspector.TimelineUIUtils.categories()["loading "]; |
169 var waitingColor = loadingCategory.backgroundColor; | 202 var waitingColor = loadingCategory.backgroundColor; |
170 var processingColor = loadingCategory.fillColorStop1; | 203 var processingColor = loadingCategory.fillColorStop1; |
171 | 204 |
172 /** | 205 /** |
173 * @param {number} band | 206 * @param {number} band |
174 * @param {number} startTime | 207 * @param {number} startTime |
175 * @param {number} endTime | 208 * @param {number} endTime |
176 * @param {?WebInspector.TracingModel.Event} event | 209 * @param {?WebInspector.TracingModel.Event} event |
177 * @this {WebInspector.TimelineEventOverview} | 210 * @this {WebInspector.TimelineEventOverview.Network} |
178 */ | 211 */ |
179 function drawBar(band, startTime, endTime, event) | 212 function drawBar(band, startTime, endTime, event) |
180 { | 213 { |
181 var start = Number.constrain((startTime - timeOffset) * scale, 0, ca nvasWidth); | 214 var start = Number.constrain((startTime - timeOffset) * scale, 0, ca nvasWidth); |
182 var end = Number.constrain((endTime - timeOffset) * scale, 0, canvas Width); | 215 var end = Number.constrain((endTime - timeOffset) * scale, 0, canvas Width); |
183 var color = !event || | 216 var color = !event || |
184 event.name === WebInspector.TimelineModel.RecordType.ResourceRec eiveResponse || | 217 event.name === WebInspector.TimelineModel.RecordType.ResourceRec eiveResponse || |
185 event.name === WebInspector.TimelineModel.RecordType.ResourceSen dRequest ? waitingColor : processingColor; | 218 event.name === WebInspector.TimelineModel.RecordType.ResourceSen dRequest ? waitingColor : processingColor; |
186 this._renderBar(Math.floor(start), Math.ceil(end), Math.floor(device PixelRatio * (position + band * bandInterval)), bandHeight, color); | 219 this._renderBar(Math.floor(start), Math.ceil(end), Math.floor(band * bandInterval), bandHeight, color); |
187 } | 220 } |
188 | 221 |
189 WebInspector.TimelineUIUtils.iterateNetworkRequestsInRoundRobin(events, bandsCount, drawBar.bind(this)); | 222 WebInspector.TimelineUIUtils.iterateNetworkRequestsInRoundRobin(events, bandsCount, drawBar.bind(this)); |
190 return height; | 223 }, |
224 | |
225 __proto__: WebInspector.TimelineEventOverview.prototype | |
226 } | |
227 | |
228 /** | |
229 * @constructor | |
230 * @extends {WebInspector.TimelineEventOverview} | |
231 * @param {string} id | |
232 * @param {!WebInspector.TimelineModel} model | |
233 */ | |
234 WebInspector.TimelineEventOverview.Thread = function(id, model) | |
235 { | |
236 WebInspector.TimelineEventOverview.call(this, id, model) | |
237 this._fillStyles = {}; | |
238 var categories = WebInspector.TimelineUIUtils.categories(); | |
239 for (var category in categories) { | |
240 this._fillStyles[category] = categories[category].fillColorStop1; | |
241 categories[category].addEventListener(WebInspector.TimelineCategory.Even ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); | |
242 } | |
243 this._disabledCategoryFillStyle = "hsl(0, 0%, 67%)"; | |
244 } | |
245 | |
246 WebInspector.TimelineEventOverview.Thread.prototype = { | |
247 /** | |
248 * @override | |
249 */ | |
250 dispose: function() | |
251 { | |
252 WebInspector.TimelineOverviewBase.prototype.dispose.call(this); | |
253 var categories = WebInspector.TimelineUIUtils.categories(); | |
254 for (var category in categories) | |
255 categories[category].removeEventListener(WebInspector.TimelineCatego ry.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this); | |
256 }, | |
257 | |
258 _onCategoryVisibilityChanged: function() | |
259 { | |
260 this.update(); | |
191 }, | 261 }, |
192 | 262 |
193 /** | 263 /** |
194 * @param {!Array.<!WebInspector.TracingModel.Event>} events | 264 * @param {!WebInspector.TimelineCategory} category |
195 * @param {number} position | 265 * @return {string} |
196 * @param {number} height | |
197 * @return {number} | |
198 */ | 266 */ |
199 _drawStackedUtilizationChart: function(events, position, height) | 267 _categoryColor: function(category) |
200 { | 268 { |
269 return category.hidden ? this._disabledCategoryFillStyle : this._fillSty les[category.name]; | |
270 }, | |
271 | |
272 __proto__: WebInspector.TimelineEventOverview.prototype | |
273 } | |
274 | |
275 /** | |
276 * @constructor | |
277 * @extends {WebInspector.TimelineEventOverview.Thread} | |
278 * @param {!WebInspector.TimelineModel} model | |
279 */ | |
280 WebInspector.TimelineEventOverview.MainThread = function(model) | |
281 { | |
282 WebInspector.TimelineEventOverview.Thread.call(this, "main-thread", model) | |
283 } | |
284 | |
285 WebInspector.TimelineEventOverview.MainThread.prototype = { | |
286 /** | |
287 * @override | |
288 */ | |
289 update: function() | |
290 { | |
291 this.resetCanvas(); | |
292 var events = this._model.mainThreadEvents(); | |
201 if (!events.length) | 293 if (!events.length) |
202 return height; | 294 return; |
203 var /** @const */ quantSizePx = 4 * window.devicePixelRatio; | 295 var /** @const */ quantSizePx = 4 * window.devicePixelRatio; |
204 var /** @const */ padding = 1; | 296 var height = this._canvas.height; |
205 var visualHeight = (height - padding) * window.devicePixelRatio; | 297 var baseLine = height; |
206 var baseLine = (position + height) * window.devicePixelRatio; | |
207 var timeOffset = this._model.minimumRecordTime(); | 298 var timeOffset = this._model.minimumRecordTime(); |
208 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 299 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
209 var scale = this._canvas.width / timeSpan; | 300 var scale = this._canvas.width / timeSpan; |
210 var quantTime = quantSizePx / scale; | 301 var quantTime = quantSizePx / scale; |
211 var quantizer = new WebInspector.Quantizer(timeOffset, quantTime, drawSa mple.bind(this)); | 302 var quantizer = new WebInspector.Quantizer(timeOffset, quantTime, drawSa mple.bind(this)); |
212 var ctx = this._context; | 303 var ctx = this._context; |
213 var x = 0; | 304 var x = 0; |
214 var categories = WebInspector.TimelineUIUtils.categories(); | 305 var categories = WebInspector.TimelineUIUtils.categories(); |
215 var categoryOrder = ["idle", "scripting", "rendering", "painting", "load ing", "other"]; | 306 var categoryOrder = ["idle", "scripting", "rendering", "painting", "load ing", "other"]; |
216 var otherIndex = categoryOrder.indexOf("other"); | 307 var otherIndex = categoryOrder.indexOf("other"); |
217 var idleIndex = 0; | 308 var idleIndex = 0; |
218 console.assert(idleIndex === categoryOrder.indexOf("idle")); | 309 console.assert(idleIndex === categoryOrder.indexOf("idle")); |
219 for (var i = idleIndex + 1; i < categoryOrder.length; ++i) | 310 for (var i = idleIndex + 1; i < categoryOrder.length; ++i) |
220 categories[categoryOrder[i]]._overviewIndex = i; | 311 categories[categoryOrder[i]]._overviewIndex = i; |
221 var categoryIndexStack = []; | 312 var categoryIndexStack = []; |
222 | 313 |
223 this._drawHorizontalGuide(baseLine - visualHeight + 0.5, WebInspector.UI String("100%")); | 314 this._drawHorizontalGuide(baseLine - height + 0.5, WebInspector.UIString ("100%")); |
224 | 315 |
225 /** | 316 /** |
226 * @param {!Array<number>} counters | 317 * @param {!Array<number>} counters |
227 * @this {WebInspector.TimelineEventOverview} | 318 * @this {WebInspector.TimelineEventOverview} |
228 */ | 319 */ |
229 function drawSample(counters) | 320 function drawSample(counters) |
230 { | 321 { |
231 var y = baseLine; | 322 var y = baseLine; |
232 for (var i = idleIndex + 1; i < counters.length; ++i) { | 323 for (var i = idleIndex + 1; i < counters.length; ++i) { |
233 if (!counters[i]) | 324 if (!counters[i]) |
234 continue; | 325 continue; |
235 var h = counters[i] / quantTime * visualHeight; | 326 var h = counters[i] / quantTime * height; |
236 ctx.fillStyle = this._categoryColor(categories[categoryOrder[i]] ); | 327 ctx.fillStyle = this._categoryColor(categories[categoryOrder[i]] ); |
237 ctx.fillRect(x, y - h, quantSizePx, h); | 328 ctx.fillRect(x, y - h, quantSizePx, h); |
238 y -= h; | 329 y -= h; |
239 } | 330 } |
240 x += quantSizePx; | 331 x += quantSizePx; |
241 } | 332 } |
242 | 333 |
243 /** | 334 /** |
244 * @param {!WebInspector.TracingModel.Event} e | 335 * @param {!WebInspector.TracingModel.Event} e |
245 */ | 336 */ |
246 function onEventStart(e) | 337 function onEventStart(e) |
247 { | 338 { |
248 var index = categoryIndexStack.length ? categoryIndexStack.peekLast( ) : idleIndex; | 339 var index = categoryIndexStack.length ? categoryIndexStack.peekLast( ) : idleIndex; |
249 quantizer.appendInterval(e.startTime, index); | 340 quantizer.appendInterval(e.startTime, index); |
250 categoryIndexStack.push(WebInspector.TimelineUIUtils.eventStyle(e).c ategory._overviewIndex || otherIndex); | 341 categoryIndexStack.push(WebInspector.TimelineUIUtils.eventStyle(e).c ategory._overviewIndex || otherIndex); |
251 } | 342 } |
252 | 343 |
253 /** | 344 /** |
254 * @param {!WebInspector.TracingModel.Event} e | 345 * @param {!WebInspector.TracingModel.Event} e |
255 */ | 346 */ |
256 function onEventEnd(e) | 347 function onEventEnd(e) |
257 { | 348 { |
258 quantizer.appendInterval(e.endTime, categoryIndexStack.pop()); | 349 quantizer.appendInterval(e.endTime, categoryIndexStack.pop()); |
259 } | 350 } |
260 | 351 |
261 WebInspector.TimelineModel.forEachEvent(events, onEventStart, onEventEnd ); | 352 WebInspector.TimelineModel.forEachEvent(events, onEventStart, onEventEnd ); |
262 quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex); // Kick drawing the last bucket. | 353 quantizer.appendInterval(timeOffset + timeSpan + quantTime, idleIndex); // Kick drawing the last bucket. |
263 return height; | 354 }, |
355 | |
356 __proto__: WebInspector.TimelineEventOverview.Thread.prototype | |
357 } | |
358 | |
359 /** | |
360 * @constructor | |
361 * @extends {WebInspector.TimelineEventOverview.Thread} | |
362 * @param {!WebInspector.TimelineModel} model | |
363 */ | |
364 WebInspector.TimelineEventOverview.OtherThreads = function(model) | |
365 { | |
366 WebInspector.TimelineEventOverview.Thread.call(this, "other-threads", model) ; | |
367 } | |
368 | |
369 WebInspector.TimelineEventOverview.OtherThreads.prototype = { | |
370 /** | |
371 * @override | |
372 */ | |
373 update: function() | |
374 { | |
375 this.resetCanvas(); | |
376 this._model.virtualThreads().forEach(this._drawThread.bind(this)); | |
264 }, | 377 }, |
265 | 378 |
266 /** | 379 /** |
267 * @param {!Array.<!WebInspector.TracingModel.Event>} events | 380 * @param {!WebInspector.TimelineModel.VirtualThread} thread |
268 * @param {number} position | |
269 * @param {number} stripHeight | |
270 * @return {number} | |
271 */ | 381 */ |
272 _drawEvents: function(events, position, stripHeight) | 382 _drawThread: function(thread) |
273 { | 383 { |
274 var /** @const */ padding = 1; | 384 var events = thread.events; |
275 var visualHeight = (stripHeight - padding) * window.devicePixelRatio; | 385 var height = this._canvas.height; |
276 var timeOffset = this._model.minimumRecordTime(); | 386 var timeOffset = this._model.minimumRecordTime(); |
277 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 387 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
278 var scale = this._canvas.width / timeSpan; | 388 var scale = this._canvas.width / timeSpan; |
279 var ditherer = new WebInspector.Dithering(); | 389 var ditherer = new WebInspector.Dithering(); |
280 var categoryStack = []; | 390 var categoryStack = []; |
281 var lastX = 0; | 391 var lastX = 0; |
282 position += padding; | |
283 position *= window.devicePixelRatio; | |
284 | 392 |
285 /** | 393 /** |
286 * @param {!WebInspector.TracingModel.Event} e | 394 * @param {!WebInspector.TracingModel.Event} e |
287 * @this {WebInspector.TimelineEventOverview} | 395 * @this {WebInspector.TimelineEventOverview} |
288 */ | 396 */ |
289 function onEventStart(e) | 397 function onEventStart(e) |
290 { | 398 { |
291 var pos = (e.startTime - timeOffset) * scale; | 399 var pos = (e.startTime - timeOffset) * scale; |
292 if (categoryStack.length) { | 400 if (categoryStack.length) { |
293 var category = categoryStack.peekLast(); | 401 var category = categoryStack.peekLast(); |
294 var bar = ditherer.appendInterval(category, lastX, pos); | 402 var bar = ditherer.appendInterval(category, lastX, pos); |
295 if (bar) | 403 if (bar) |
296 this._renderBar(bar.start, bar.end, position, visualHeight, this._categoryColor(category)); | 404 this._renderBar(bar.start, bar.end, 0, height, this._categor yColor(category)); |
297 } | 405 } |
298 categoryStack.push(WebInspector.TimelineUIUtils.eventStyle(e).catego ry); | 406 categoryStack.push(WebInspector.TimelineUIUtils.eventStyle(e).catego ry); |
299 lastX = pos; | 407 lastX = pos; |
300 } | 408 } |
301 | 409 |
302 /** | 410 /** |
303 * @param {!WebInspector.TracingModel.Event} e | 411 * @param {!WebInspector.TracingModel.Event} e |
304 * @this {WebInspector.TimelineEventOverview} | 412 * @this {WebInspector.TimelineEventOverview} |
305 */ | 413 */ |
306 function onEventEnd(e) | 414 function onEventEnd(e) |
307 { | 415 { |
308 var category = categoryStack.pop(); | 416 var category = categoryStack.pop(); |
309 var pos = (e.endTime - timeOffset) * scale; | 417 var pos = (e.endTime - timeOffset) * scale; |
310 var bar = ditherer.appendInterval(category, lastX, pos); | 418 var bar = ditherer.appendInterval(category, lastX, pos); |
311 if (bar) | 419 if (bar) |
312 this._renderBar(bar.start, bar.end, position, visualHeight, this ._categoryColor(category)); | 420 this._renderBar(bar.start, bar.end, 0, height, this._categoryCol or(category)); |
313 lastX = pos; | 421 lastX = pos; |
314 } | 422 } |
315 | 423 |
316 WebInspector.TimelineModel.forEachEvent(events, onEventStart.bind(this), onEventEnd.bind(this)); | 424 WebInspector.TimelineModel.forEachEvent(events, onEventStart.bind(this), onEventEnd.bind(this)); |
317 return stripHeight; | |
318 }, | 425 }, |
319 | 426 |
427 __proto__: WebInspector.TimelineEventOverview.Thread.prototype | |
428 } | |
429 | |
430 /** | |
431 * @constructor | |
432 * @extends {WebInspector.TimelineEventOverview} | |
433 * @param {!WebInspector.TimelineModel} model | |
434 * @param {!WebInspector.TimelineFrameModelBase} frameModel | |
435 */ | |
436 WebInspector.TimelineEventOverview.Responsiveness = function(model, frameModel) | |
437 { | |
438 WebInspector.TimelineEventOverview.call(this, "responsiveness", model) | |
439 this._frameModel = frameModel; | |
440 } | |
441 | |
442 WebInspector.TimelineEventOverview.Responsiveness.prototype = { | |
320 /** | 443 /** |
321 * @param {!WebInspector.TimelineCategory} category | 444 * @override |
322 * @return {string} | |
323 */ | 445 */ |
324 _categoryColor: function(category) | 446 update: function() |
325 { | 447 { |
326 return category.hidden ? this._disabledCategoryFillStyle : this._fillSty les[category.name]; | 448 this.resetCanvas(); |
327 }, | 449 var height = this._canvas.height; |
328 | |
329 /** | |
330 * @param {number} position | |
331 * @param {number} height | |
332 * @return {number} | |
333 */ | |
334 _drawResponsivenessStrip: function(position, height) | |
335 { | |
336 var /** @const */ padding = 1; | |
337 var visualHeight = (height - padding) * window.devicePixelRatio; | |
338 var timeOffset = this._model.minimumRecordTime(); | 450 var timeOffset = this._model.minimumRecordTime(); |
339 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 451 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
340 var scale = this._canvas.width / timeSpan; | 452 var scale = this._canvas.width / timeSpan; |
341 var frames = this._frameModel.frames(); | 453 var frames = this._frameModel.frames(); |
342 var ctx = this._context; | 454 var ctx = this._context; |
343 ctx.beginPath(); | 455 ctx.beginPath(); |
344 var responsivenessStripY = (position + padding) * window.devicePixelRati o; | 456 var responsivenessStripY = (0 + 0) * window.devicePixelRatio; |
345 for (var i = 0; i < frames.length; ++i) { | 457 for (var i = 0; i < frames.length; ++i) { |
346 var frame = frames[i]; | 458 var frame = frames[i]; |
347 if (!frame.hasWarnings()) | 459 if (!frame.hasWarnings()) |
348 continue; | 460 continue; |
349 var x = scale * (frame.startTime - timeOffset); | 461 var x = scale * (frame.startTime - timeOffset); |
350 var w = scale * frame.duration; | 462 var w = scale * frame.duration; |
351 ctx.rect(x, responsivenessStripY, w, visualHeight); | 463 ctx.rect(x, responsivenessStripY, w, height); |
352 } | 464 } |
353 ctx.fillStyle = "hsl(0, 80%, 70%)"; | 465 ctx.fillStyle = "hsl(0, 80%, 70%)"; |
354 ctx.fill(); | 466 ctx.fill(); |
355 return height; | |
356 }, | 467 }, |
357 | 468 |
469 __proto__: WebInspector.TimelineEventOverview.prototype | |
470 } | |
471 | |
472 /** | |
473 * @constructor | |
474 * @extends {WebInspector.TimelineEventOverview} | |
475 * @param {!WebInspector.TimelineModel} model | |
476 * @param {!WebInspector.TimelineFrameModelBase} frameModel | |
477 */ | |
478 WebInspector.TimelineEventOverview.Frames = function(model, frameModel) | |
479 { | |
480 WebInspector.TimelineEventOverview.call(this, "framerate", model); | |
481 this._frameModel = frameModel; | |
482 } | |
483 | |
484 WebInspector.TimelineEventOverview.Frames.prototype = { | |
358 /** | 485 /** |
359 * @param {number} position | 486 * @override |
360 * @param {number} height | |
361 * @return {number} | |
362 */ | 487 */ |
363 _drawFrames: function(position, height) | 488 update: function() |
364 { | 489 { |
365 var /** @const */ padding = 2; | 490 this.resetCanvas(); |
491 var height = this._canvas.height; | |
492 var /** @const */ padding = 1 * window.devicePixelRatio; | |
366 var /** @const */ baseFrameDurationMs = 1e3 / 60; | 493 var /** @const */ baseFrameDurationMs = 1e3 / 60; |
367 var visualHeight = (height - padding) * window.devicePixelRatio; | 494 var visualHeight = height - 2 * padding; |
368 var timeOffset = this._model.minimumRecordTime(); | 495 var timeOffset = this._model.minimumRecordTime(); |
369 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 496 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
370 var scale = this._canvas.width / timeSpan; | 497 var scale = this._canvas.width / timeSpan; |
371 var frames = this._frameModel.frames(); | 498 var frames = this._frameModel.frames(); |
372 var baseY = height * window.devicePixelRatio; | 499 var baseY = height - padding; |
373 var ctx = this._context; | 500 var ctx = this._context; |
374 var y = baseY + 10; | 501 var bottomY = baseY + 10 * window.devicePixelRatio; |
502 var y = bottomY; | |
375 if (!frames.length) | 503 if (!frames.length) |
376 return height; | 504 return; |
377 | |
378 ctx.save(); | |
379 ctx.translate(0, position * window.devicePixelRatio); | |
380 ctx.beginPath(); | |
381 ctx.rect(0, 0, this._canvas.width, height * window.devicePixelRatio); | |
382 ctx.clip(); | |
383 | 505 |
384 this._drawHorizontalGuide(baseY - visualHeight - 0.5, WebInspector.UIStr ing("60\u2009fps")); | 506 this._drawHorizontalGuide(baseY - visualHeight - 0.5, WebInspector.UIStr ing("60\u2009fps")); |
385 | 507 |
386 var lineWidth = window.devicePixelRatio; | 508 var lineWidth = window.devicePixelRatio; |
387 var offset = lineWidth & 1 ? 0.5 : 0; | 509 var offset = lineWidth & 1 ? 0.5 : 0; |
388 var tickDepth = 1.5 * window.devicePixelRatio; | 510 var tickDepth = 1.5 * window.devicePixelRatio; |
389 ctx.beginPath(); | 511 ctx.beginPath(); |
390 ctx.moveTo(0, y); | 512 ctx.moveTo(0, y); |
391 for (var i = 0; i < frames.length; ++i) { | 513 for (var i = 0; i < frames.length; ++i) { |
392 var frame = frames[i]; | 514 var frame = frames[i]; |
393 var x = Math.round((frame.startTime - timeOffset) * scale) + offset; | 515 var x = Math.round((frame.startTime - timeOffset) * scale) + offset; |
394 ctx.lineTo(x, y); | 516 ctx.lineTo(x, y); |
395 ctx.lineTo(x, y + tickDepth); | 517 ctx.lineTo(x, y + tickDepth); |
396 y = frame.idle ? baseY + 1 : Math.round(baseY - visualHeight * Math. min(baseFrameDurationMs / frame.duration, 1)) - offset; | 518 y = frame.idle ? bottomY : Math.round(baseY - visualHeight * Math.mi n(baseFrameDurationMs / frame.duration, 1)) - offset; |
397 ctx.lineTo(x, y + tickDepth); | 519 ctx.lineTo(x, y + tickDepth); |
398 ctx.lineTo(x, y); | 520 ctx.lineTo(x, y); |
399 } | 521 } |
400 if (frames.length) { | 522 if (frames.length) { |
401 var lastFrame = frames.peekLast(); | 523 var lastFrame = frames.peekLast(); |
402 var x = Math.round((lastFrame.startTime + lastFrame.duration - timeO ffset) * scale) + offset; | 524 var x = Math.round((lastFrame.startTime + lastFrame.duration - timeO ffset) * scale) + offset; |
403 ctx.lineTo(x, y); | 525 ctx.lineTo(x, y); |
404 } | 526 } |
405 ctx.lineTo(x, baseY + 10); | 527 ctx.lineTo(x, bottomY); |
406 ctx.fillStyle = "hsl(110, 50%, 88%)"; | 528 ctx.fillStyle = "hsl(110, 50%, 88%)"; |
407 ctx.strokeStyle = "hsl(110, 50%, 60%)"; | 529 ctx.strokeStyle = "hsl(110, 50%, 60%)"; |
408 ctx.lineWidth = lineWidth; | 530 ctx.lineWidth = lineWidth; |
409 ctx.fill(); | 531 ctx.fill(); |
410 ctx.stroke(); | 532 ctx.stroke(); |
411 ctx.restore(); | |
412 return height; | |
413 }, | 533 }, |
414 | 534 |
415 /** | 535 __proto__: WebInspector.TimelineEventOverview.prototype |
416 * @param {number} y | |
417 * @param {string} label | |
418 */ | |
419 _drawHorizontalGuide: function(y, label) | |
420 { | |
421 var ctx = this._context; | |
422 ctx.save(); | |
423 ctx.translate(0, y); | |
424 ctx.scale(window.devicePixelRatio, window.devicePixelRatio); | |
425 ctx.beginPath(); | |
426 ctx.moveTo(0, 0); | |
427 ctx.lineTo(this._canvas.width, 0); | |
428 ctx.strokeStyle = "hsl(0, 0%, 85%)"; | |
429 ctx.setLineDash([3]); | |
430 ctx.lineWidth = 1; | |
431 ctx.stroke(); | |
432 ctx.fillStyle = "hsl(0, 0%, 70%)"; | |
433 ctx.font = "9px " + WebInspector.fontFamily(); | |
434 ctx.fillText(label, 4, 9); | |
435 ctx.restore(); | |
436 }, | |
437 | |
438 _onCategoryVisibilityChanged: function() | |
439 { | |
440 this.update(); | |
441 }, | |
442 | |
443 /** | |
444 * @param {number} begin | |
445 * @param {number} end | |
446 * @param {number} position | |
447 * @param {number} height | |
448 * @param {string} color | |
449 */ | |
450 _renderBar: function(begin, end, position, height, color) | |
451 { | |
452 var x = begin; | |
453 var width = end - begin; | |
454 this._context.fillStyle = color; | |
455 this._context.fillRect(x, position, width, height); | |
456 }, | |
457 | |
458 /** | |
459 * @override | |
460 * @param {number} windowLeft | |
461 * @param {number} windowRight | |
462 * @return {!{startTime: number, endTime: number}} | |
463 */ | |
464 windowTimes: function(windowLeft, windowRight) | |
465 { | |
466 var absoluteMin = this._model.minimumRecordTime(); | |
467 var timeSpan = this._model.maximumRecordTime() - absoluteMin; | |
468 return { | |
469 startTime: absoluteMin + timeSpan * windowLeft, | |
470 endTime: absoluteMin + timeSpan * windowRight | |
471 }; | |
472 }, | |
473 | |
474 /** | |
475 * @override | |
476 * @param {number} startTime | |
477 * @param {number} endTime | |
478 * @return {!{left: number, right: number}} | |
479 */ | |
480 windowBoundaries: function(startTime, endTime) | |
481 { | |
482 var absoluteMin = this._model.minimumRecordTime(); | |
483 var timeSpan = this._model.maximumRecordTime() - absoluteMin; | |
484 var haveRecords = absoluteMin > 0; | |
485 return { | |
486 left: haveRecords && startTime ? Math.min((startTime - absoluteMin) / timeSpan, 1) : 0, | |
487 right: haveRecords && endTime < Infinity ? (endTime - absoluteMin) / timeSpan : 1 | |
488 }; | |
489 }, | |
490 | |
491 __proto__: WebInspector.TimelineOverviewBase.prototype | |
492 } | 536 } |
493 | 537 |
494 /** | 538 /** |
495 * @constructor | 539 * @constructor |
496 * @template T | 540 * @template T |
497 */ | 541 */ |
498 WebInspector.Dithering = function() | 542 WebInspector.Dithering = function() |
499 { | 543 { |
500 /** @type {!Map.<?T,number>} */ | 544 /** @type {!Map.<?T,number>} */ |
501 this._groupError = new Map(); | 545 this._groupError = new Map(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 counters[group] = this._quantDuration; | 650 counters[group] = this._quantDuration; |
607 this._callback(counters); | 651 this._callback(counters); |
608 interval -= this._quantDuration; | 652 interval -= this._quantDuration; |
609 } | 653 } |
610 this._counters = []; | 654 this._counters = []; |
611 this._counters[group] = interval; | 655 this._counters[group] = interval; |
612 this._lastTime = time; | 656 this._lastTime = time; |
613 this._remainder = this._quantDuration - interval; | 657 this._remainder = this._quantDuration - interval; |
614 } | 658 } |
615 } | 659 } |
OLD | NEW |