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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 for (var category in categories) { | 43 for (var category in categories) { |
44 this._fillStyles[category] = categories[category].fillColorStop1; | 44 this._fillStyles[category] = categories[category].fillColorStop1; |
45 categories[category].addEventListener(WebInspector.TimelineCategory.Even
ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); | 45 categories[category].addEventListener(WebInspector.TimelineCategory.Even
ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); |
46 } | 46 } |
47 | 47 |
48 this._disabledCategoryFillStyle = "hsl(0, 0%, 67%)"; | 48 this._disabledCategoryFillStyle = "hsl(0, 0%, 67%)"; |
49 } | 49 } |
50 | 50 |
51 /** @const */ | 51 /** @const */ |
52 WebInspector.TimelineEventOverview._stripHeight = 10; | 52 WebInspector.TimelineEventOverview._stripHeight = 10; |
| 53 /** @const */ |
| 54 WebInspector.TimelineEventOverview._maxNetworkStripHeight = 32; |
53 | 55 |
54 WebInspector.TimelineEventOverview.prototype = { | 56 WebInspector.TimelineEventOverview.prototype = { |
55 /** | 57 /** |
56 * @override | 58 * @override |
57 */ | 59 */ |
58 dispose: function() | 60 dispose: function() |
59 { | 61 { |
60 var categories = WebInspector.TimelineUIUtils.categories(); | 62 var categories = WebInspector.TimelineUIUtils.categories(); |
61 for (var category in categories) | 63 for (var category in categories) |
62 categories[category].removeEventListener(WebInspector.TimelineCatego
ry.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this); | 64 categories[category].removeEventListener(WebInspector.TimelineCatego
ry.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this); |
63 }, | 65 }, |
64 | 66 |
65 /** | 67 /** |
66 * @override | 68 * @override |
67 */ | 69 */ |
68 update: function() | 70 update: function() |
69 { | 71 { |
70 var /** @const */ topPadding = 2; | 72 var /** @const */ padding = 2; |
71 this.resetCanvas(); | 73 this.resetCanvas(); |
72 var threads = this._model.virtualThreads(); | 74 var threads = this._model.virtualThreads(); |
73 var estimatedHeight = 3 * WebInspector.TimelineEventOverview._stripHeigh
t; | 75 var mainThreadEvents = this._model.mainThreadEvents(); |
| 76 var estimatedHeight = padding + 3 * WebInspector.TimelineEventOverview._
stripHeight; |
| 77 estimatedHeight += padding + WebInspector.TimelineEventOverview._maxNetw
orkStripHeight; |
74 this._canvas.height = estimatedHeight * window.devicePixelRatio; | 78 this._canvas.height = estimatedHeight * window.devicePixelRatio; |
75 this._canvas.style.height = estimatedHeight + "px"; | 79 this._canvas.style.height = estimatedHeight + "px"; |
76 var position = topPadding; | 80 var position = padding; |
77 position += this._drawEvents(this._model.mainThreadEvents(), position); | 81 if (Runtime.experiments.isEnabled("networkRequestsOnTimeline")) { |
| 82 position += this._drawNetwork(mainThreadEvents, position); |
| 83 position += padding; |
| 84 } |
| 85 this._drawEvents(mainThreadEvents, position); |
| 86 position += WebInspector.TimelineEventOverview._stripHeight; |
78 for (var thread of threads.filter(function(thread) { return !thread.isWo
rker(); })) | 87 for (var thread of threads.filter(function(thread) { return !thread.isWo
rker(); })) |
79 this._drawEvents(thread.events, position); | 88 this._drawEvents(thread.events, position); |
80 position += WebInspector.TimelineEventOverview._stripHeight; | 89 position += WebInspector.TimelineEventOverview._stripHeight; |
81 var workersHeight = 0; | 90 var workersHeight = 0; |
82 for (var thread of threads.filter(function(thread) { return thread.isWor
ker(); })) | 91 for (var thread of threads.filter(function(thread) { return thread.isWor
ker(); })) |
83 workersHeight = Math.max(workersHeight, this._drawEvents(thread.even
ts, position)); | 92 workersHeight = Math.max(workersHeight, this._drawEvents(thread.even
ts, position)); |
84 position += workersHeight; | 93 position += workersHeight; |
85 this.element.style.flexBasis = position + "px"; | 94 this.element.style.flexBasis = position + "px"; |
86 }, | 95 }, |
87 | 96 |
88 /** | 97 /** |
89 * @param {!Array.<!WebInspector.TracingModel.Event>} events | 98 * @param {!Array.<!WebInspector.TracingModel.Event>} events |
90 * @param {number} position | 99 * @param {number} position |
91 * @return {number} | 100 * @return {number} |
92 */ | 101 */ |
| 102 _drawNetwork: function(events, position) |
| 103 { |
| 104 /** |
| 105 * @param {!Array.<!WebInspector.TracingModel.Event>} events |
| 106 * @return {number} |
| 107 */ |
| 108 function calculateNetworkBandsCount(events) |
| 109 { |
| 110 var openBands = new Set(); |
| 111 var maxBands = 0; |
| 112 for (var i = 0; i < events.length; ++i) { |
| 113 var e = events[i]; |
| 114 switch (e.name) { |
| 115 case WebInspector.TimelineModel.RecordType.ResourceSendRequest: |
| 116 case WebInspector.TimelineModel.RecordType.ResourceReceiveRespon
se: |
| 117 case WebInspector.TimelineModel.RecordType.ResourceReceivedData: |
| 118 var reqId = e.args["data"]["requestId"]; |
| 119 openBands.add(reqId); |
| 120 maxBands = Math.max(maxBands, openBands.size); |
| 121 break; |
| 122 case WebInspector.TimelineModel.RecordType.ResourceFinish: |
| 123 var reqId = e.args["data"]["requestId"]; |
| 124 if (!openBands.has(reqId)) |
| 125 ++maxBands; |
| 126 else |
| 127 openBands.delete(reqId); |
| 128 break; |
| 129 } |
| 130 } |
| 131 return maxBands; |
| 132 } |
| 133 |
| 134 var /** @const */ maxBandHeight = 4; |
| 135 var bandsCount = calculateNetworkBandsCount(events); |
| 136 var bandInterval = Math.min(maxBandHeight, WebInspector.TimelineEventOve
rview._maxNetworkStripHeight / (bandsCount || 1)); |
| 137 var bandHeight = Math.ceil(bandInterval); |
| 138 var timeOffset = this._model.minimumRecordTime(); |
| 139 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
| 140 var scale = this._canvas.width / timeSpan; |
| 141 var loadingCategory = WebInspector.TimelineUIUtils.categories()["loading
"]; |
| 142 var waitingColor = loadingCategory.fillColorStop0; |
| 143 var processingColor = loadingCategory.fillColorStop1; |
| 144 |
| 145 var bandsInUse = new Array(bandsCount); |
| 146 var freeBandsCount = bandsCount; |
| 147 var requestsInFlight = new Map(); |
| 148 var lastBand = 0; |
| 149 |
| 150 /** |
| 151 * @constructor |
| 152 * @param {number} band |
| 153 * @param {number} lastTime |
| 154 * @param {boolean} gotResponse |
| 155 */ |
| 156 function RequestInfo(band, lastTime, gotResponse) |
| 157 { |
| 158 this.band = band; |
| 159 this.lastTime = lastTime; |
| 160 this.gotResponse = gotResponse; |
| 161 } |
| 162 |
| 163 /** |
| 164 * @return {number} |
| 165 */ |
| 166 function seizeBand() |
| 167 { |
| 168 console.assert(freeBandsCount); |
| 169 do { |
| 170 lastBand = (lastBand + 1) % bandsInUse.length; |
| 171 } while (bandsInUse[lastBand]); |
| 172 bandsInUse[lastBand] = true; |
| 173 --freeBandsCount; |
| 174 return lastBand; |
| 175 } |
| 176 |
| 177 /** |
| 178 * @param {number} band |
| 179 */ |
| 180 function releaseBand(band) |
| 181 { |
| 182 bandsInUse[band] = false; |
| 183 ++freeBandsCount; |
| 184 } |
| 185 |
| 186 /** |
| 187 * @param {string} reqId |
| 188 * @param {number=} time |
| 189 * @return {!RequestInfo} |
| 190 */ |
| 191 function getRequestInfo(reqId, time) |
| 192 { |
| 193 var reqInfo = requestsInFlight.get(reqId); |
| 194 if (!reqInfo) { |
| 195 reqInfo = new RequestInfo(seizeBand(), time || timeOffset, false
); |
| 196 requestsInFlight.set(reqId, reqInfo); |
| 197 } |
| 198 return reqInfo; |
| 199 } |
| 200 |
| 201 /** |
| 202 * @param {string} reqId |
| 203 * @param {!RequestInfo} reqInfo |
| 204 * @param {number} time |
| 205 * @param {boolean=} finish |
| 206 * @this {WebInspector.TimelineEventOverview} |
| 207 */ |
| 208 function advanceRequest(reqId, reqInfo, time, finish) |
| 209 { |
| 210 var band = reqInfo.band; |
| 211 var start = (reqInfo.lastTime - timeOffset) * scale; |
| 212 var end = (time - timeOffset) * scale; |
| 213 var color = reqInfo.gotResponse ? processingColor : waitingColor; |
| 214 if (finish) { |
| 215 releaseBand(band); |
| 216 requestsInFlight.delete(reqId); |
| 217 } else { |
| 218 reqInfo.lastTime = time; |
| 219 reqInfo.gotResponse = true; |
| 220 } |
| 221 this._renderBar(Math.floor(start), Math.ceil(end), Math.floor(positi
on + band * bandInterval), bandHeight, color); |
| 222 } |
| 223 |
| 224 for (var i = 0; i < events.length; ++i) { |
| 225 var event = events[i]; |
| 226 switch (event.name) { |
| 227 case WebInspector.TimelineModel.RecordType.ResourceSendRequest: |
| 228 var reqId = event.args["data"]["requestId"]; |
| 229 getRequestInfo(reqId, event.startTime); |
| 230 break; |
| 231 case WebInspector.TimelineModel.RecordType.ResourceReceivedData: |
| 232 case WebInspector.TimelineModel.RecordType.ResourceReceiveResponse: |
| 233 case WebInspector.TimelineModel.RecordType.ResourceFinish: |
| 234 var reqId = event.args["data"]["requestId"]; |
| 235 var reqInfo = getRequestInfo(reqId); |
| 236 var finish = event.name === WebInspector.TimelineModel.RecordTyp
e.ResourceFinish; |
| 237 advanceRequest.call(this, reqId, reqInfo, event.startTime, finis
h); |
| 238 break; |
| 239 } |
| 240 } |
| 241 |
| 242 for (var reqId of requestsInFlight.keys()) |
| 243 advanceRequest.call(this, reqId, requestsInFlight.get(reqId), timeOf
fset + timeSpan); |
| 244 |
| 245 return Math.ceil(bandInterval * bandsCount); |
| 246 }, |
| 247 |
| 248 /** |
| 249 * @param {!Array.<!WebInspector.TracingModel.Event>} events |
| 250 * @param {number} position |
| 251 * @return {number} |
| 252 */ |
93 _drawEvents: function(events, position) | 253 _drawEvents: function(events, position) |
94 { | 254 { |
| 255 var /** @const */ padding = 1; |
95 var stripHeight = WebInspector.TimelineEventOverview._stripHeight; | 256 var stripHeight = WebInspector.TimelineEventOverview._stripHeight; |
| 257 var visualHeight = stripHeight - padding; |
96 var timeOffset = this._model.minimumRecordTime(); | 258 var timeOffset = this._model.minimumRecordTime(); |
97 var timeSpan = this._model.maximumRecordTime() - timeOffset; | 259 var timeSpan = this._model.maximumRecordTime() - timeOffset; |
98 var scale = this._canvas.width / timeSpan; | 260 var scale = this._canvas.width / timeSpan; |
99 var ditherer = new WebInspector.Dithering(); | 261 var ditherer = new WebInspector.Dithering(); |
100 var categoryStack = []; | 262 var categoryStack = []; |
101 var lastX = 0; | 263 var lastX = 0; |
102 var drawn = false; | 264 var drawn = false; |
103 | 265 |
104 /** | 266 /** |
| 267 * @param {!WebInspector.TimelineCategory} category |
| 268 * @return {string} |
| 269 * @this {WebInspector.TimelineEventOverview} |
| 270 */ |
| 271 function categoryColor(category) |
| 272 { |
| 273 return category.hidden ? this._disabledCategoryFillStyle : this._fil
lStyles[category.name]; |
| 274 } |
| 275 |
| 276 /** |
105 * @param {!WebInspector.TracingModel.Event} e | 277 * @param {!WebInspector.TracingModel.Event} e |
106 * @this {WebInspector.TimelineEventOverview} | 278 * @this {WebInspector.TimelineEventOverview} |
107 */ | 279 */ |
108 function onEventStart(e) | 280 function onEventStart(e) |
109 { | 281 { |
110 var pos = (e.startTime - timeOffset) * scale; | 282 var pos = (e.startTime - timeOffset) * scale; |
111 if (categoryStack.length) { | 283 if (categoryStack.length) { |
112 var category = categoryStack.peekLast(); | 284 var category = categoryStack.peekLast(); |
113 var bar = ditherer.appendInterval(category, lastX, pos); | 285 var bar = ditherer.appendInterval(category, lastX, pos); |
114 if (bar) { | 286 if (bar) { |
115 this._renderBar(bar.start, bar.end, position, stripHeight, c
ategory); | 287 this._renderBar(bar.start, bar.end, position, visualHeight,
categoryColor.call(this, category)); |
116 drawn = true; | 288 drawn = true; |
117 } | 289 } |
118 } | 290 } |
119 categoryStack.push(WebInspector.TimelineUIUtils.eventStyle(e).catego
ry); | 291 categoryStack.push(WebInspector.TimelineUIUtils.eventStyle(e).catego
ry); |
120 lastX = pos; | 292 lastX = pos; |
121 } | 293 } |
122 | 294 |
123 /** | 295 /** |
124 * @param {!WebInspector.TracingModel.Event} e | 296 * @param {!WebInspector.TracingModel.Event} e |
125 * @this {WebInspector.TimelineEventOverview} | 297 * @this {WebInspector.TimelineEventOverview} |
126 */ | 298 */ |
127 function onEventEnd(e) | 299 function onEventEnd(e) |
128 { | 300 { |
129 var category = categoryStack.pop(); | 301 var category = categoryStack.pop(); |
130 var pos = (e.endTime - timeOffset) * scale; | 302 var pos = (e.endTime - timeOffset) * scale; |
131 var bar = ditherer.appendInterval(category, lastX, pos); | 303 var bar = ditherer.appendInterval(category, lastX, pos); |
132 if (bar) { | 304 if (bar) { |
133 this._renderBar(bar.start, bar.end, position, stripHeight, categ
ory); | 305 this._renderBar(bar.start, bar.end, position, visualHeight, cate
goryColor.call(this, category)); |
134 drawn = true; | 306 drawn = true; |
135 } | 307 } |
136 lastX = pos; | 308 lastX = pos; |
137 } | 309 } |
138 | 310 |
139 WebInspector.TimelineModel.forEachEvent(events, onEventStart.bind(this),
onEventEnd.bind(this)); | 311 WebInspector.TimelineModel.forEachEvent(events, onEventStart.bind(this),
onEventEnd.bind(this)); |
140 return drawn ? stripHeight : 0; | 312 return drawn ? stripHeight : 0; |
141 }, | 313 }, |
142 | 314 |
143 _onCategoryVisibilityChanged: function() | 315 _onCategoryVisibilityChanged: function() |
144 { | 316 { |
145 this.update(); | 317 this.update(); |
146 }, | 318 }, |
147 | 319 |
148 /** | 320 /** |
149 * @param {number} begin | 321 * @param {number} begin |
150 * @param {number} end | 322 * @param {number} end |
151 * @param {number} position | 323 * @param {number} position |
152 * @param {number} height | 324 * @param {number} height |
153 * @param {!WebInspector.TimelineCategory} category | 325 * @param {string} color |
154 */ | 326 */ |
155 _renderBar: function(begin, end, position, height, category) | 327 _renderBar: function(begin, end, position, height, color) |
156 { | 328 { |
157 var /** @const */ stripPadding = 1; | |
158 var innerStripHeight = (height - stripPadding) * window.devicePixelRatio
; | |
159 var x = begin; | 329 var x = begin; |
160 var y = position * window.devicePixelRatio; | 330 var y = position * window.devicePixelRatio; |
161 var width = end - begin; | 331 var width = end - begin; |
162 this._context.fillStyle = category.hidden ? this._disabledCategoryFillSt
yle : this._fillStyles[category.name]; | 332 this._context.fillStyle = color; |
163 this._context.fillRect(x, y, width, innerStripHeight); | 333 this._context.fillRect(x, y, width, height * window.devicePixelRatio); |
164 }, | 334 }, |
165 | 335 |
166 __proto__: WebInspector.TimelineOverviewBase.prototype | 336 __proto__: WebInspector.TimelineOverviewBase.prototype |
167 } | 337 } |
168 | 338 |
169 /** | 339 /** |
170 * @constructor | 340 * @constructor |
171 * @template T | 341 * @template T |
172 */ | 342 */ |
173 WebInspector.Dithering = function() | 343 WebInspector.Dithering = function() |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 for (var g of this._groupError.keys()) { | 406 for (var g of this._groupError.keys()) { |
237 if (!g) | 407 if (!g) |
238 continue; | 408 continue; |
239 var value = this._groupError.get(g); | 409 var value = this._groupError.get(g); |
240 value += (1 - value) * ratio; | 410 value += (1 - value) * ratio; |
241 this._groupError.set(g, value); | 411 this._groupError.set(g, value); |
242 } | 412 } |
243 return toDistribute; | 413 return toDistribute; |
244 } | 414 } |
245 } | 415 } |
OLD | NEW |