Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: Source/devtools/front_end/timeline/TimelineEventOverview.js

Issue 1211993002: DevTools: Refactor: Split timeline overview strips into components (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | Source/devtools/front_end/timeline/TimelinePanel.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | Source/devtools/front_end/timeline/TimelinePanel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698