OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 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 16 matching lines...) Expand all Loading... |
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.Object} | 33 * @extends {WebInspector.Object} |
34 */ | 34 */ |
35 WebInspector.TimelineModel = function() | 35 WebInspector.TimelineModel = function() |
36 { | 36 { |
| 37 this._payloads = []; |
37 this._records = []; | 38 this._records = []; |
38 this._minimumRecordTime = -1; | 39 this._minimumRecordTime = -1; |
39 this._maximumRecordTime = -1; | 40 this._maximumRecordTime = -1; |
40 this._stringPool = {}; | 41 this._stringPool = {}; |
| 42 this._bindings = new WebInspector.TimelineModel.InterRecordBindings(); |
41 | 43 |
42 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineEventRecorded, this._onRecordAdded, this); | 44 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineEventRecorded, this._onRecordAdded, this); |
43 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineStarted, this._onStarted, this); | 45 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineStarted, this._onStarted, this); |
44 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineStopped, this._onStopped, this); | 46 WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.E
ventTypes.TimelineStopped, this._onStopped, this); |
45 } | 47 } |
46 | 48 |
47 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; | 49 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; |
48 | 50 |
49 WebInspector.TimelineModel.RecordType = { | 51 WebInspector.TimelineModel.RecordType = { |
50 Root: "Root", | 52 Root: "Root", |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 EmbedderCallback : "EmbedderCallback", | 110 EmbedderCallback : "EmbedderCallback", |
109 } | 111 } |
110 | 112 |
111 WebInspector.TimelineModel.Events = { | 113 WebInspector.TimelineModel.Events = { |
112 RecordAdded: "RecordAdded", | 114 RecordAdded: "RecordAdded", |
113 RecordsCleared: "RecordsCleared", | 115 RecordsCleared: "RecordsCleared", |
114 RecordingStarted: "RecordingStarted", | 116 RecordingStarted: "RecordingStarted", |
115 RecordingStopped: "RecordingStopped" | 117 RecordingStopped: "RecordingStopped" |
116 } | 118 } |
117 | 119 |
| 120 /** |
| 121 * @param {!Array.<!WebInspector.TimelineModel.Record>} recordsArray |
| 122 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspector
.TimelineModel.Record,number)} preOrderCallback |
| 123 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspector.T
imelineModel.Record,number)=} postOrderCallback |
| 124 */ |
| 125 WebInspector.TimelineModel.forAllRecords = function(recordsArray, preOrderCallba
ck, postOrderCallback) |
| 126 { |
| 127 if (!recordsArray) |
| 128 return; |
| 129 var stack = [{array: recordsArray, index: 0}]; |
| 130 while (stack.length) { |
| 131 var entry = stack[stack.length - 1]; |
| 132 var records = entry.array; |
| 133 if (entry.index < records.length) { |
| 134 var record = records[entry.index]; |
| 135 if (preOrderCallback && preOrderCallback(record, stack.length)) |
| 136 return; |
| 137 if (record.children) |
| 138 stack.push({array: record.children, index: 0, record: record}); |
| 139 else if (postOrderCallback && postOrderCallback(record, stack.lengt
h)) |
| 140 return; |
| 141 ++entry.index; |
| 142 } else { |
| 143 if (entry.record && postOrderCallback && postOrderCallback(entry.rec
ord, stack.length)) |
| 144 return; |
| 145 stack.pop(); |
| 146 } |
| 147 } |
| 148 } |
| 149 |
118 WebInspector.TimelineModel.prototype = { | 150 WebInspector.TimelineModel.prototype = { |
119 /** | 151 /** |
| 152 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspe
ctor.TimelineModel.Record,number)} preOrderCallback |
| 153 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect
or.TimelineModel.Record,number)=} postOrderCallback |
| 154 */ |
| 155 forAllRecords: function(preOrderCallback, postOrderCallback) |
| 156 { |
| 157 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback
, postOrderCallback); |
| 158 }, |
| 159 |
| 160 /** |
120 * @param {boolean=} includeCounters | 161 * @param {boolean=} includeCounters |
121 */ | 162 */ |
122 startRecording: function(includeCounters) | 163 startRecording: function(includeCounters) |
123 { | 164 { |
124 this._clientInitiatedRecording = true; | 165 this._clientInitiatedRecording = true; |
125 this.reset(); | 166 this.reset(); |
126 var maxStackFrames = WebInspector.settings.timelineCaptureStacks.get() ?
30 : 0; | 167 var maxStackFrames = WebInspector.settings.timelineCaptureStacks.get() ?
30 : 0; |
127 var includeGPUEvents = WebInspector.experimentsSettings.gpuTimeline.isEn
abled(); | 168 var includeGPUEvents = WebInspector.experimentsSettings.gpuTimeline.isEn
abled(); |
128 WebInspector.timelineManager.start(maxStackFrames, includeCounters, incl
udeGPUEvents, this._fireRecordingStarted.bind(this)); | 169 WebInspector.timelineManager.start(maxStackFrames, includeCounters, incl
udeGPUEvents, this._fireRecordingStarted.bind(this)); |
129 }, | 170 }, |
(...skipping 12 matching lines...) Expand all Loading... |
142 */ | 183 */ |
143 function stopTimeline() | 184 function stopTimeline() |
144 { | 185 { |
145 WebInspector.timelineManager.stop(this._fireRecordingStopped.bind(th
is)); | 186 WebInspector.timelineManager.stop(this._fireRecordingStopped.bind(th
is)); |
146 } | 187 } |
147 | 188 |
148 this._clientInitiatedRecording = false; | 189 this._clientInitiatedRecording = false; |
149 WebInspector.timelineManager.stop(this._fireRecordingStopped.bind(this))
; | 190 WebInspector.timelineManager.stop(this._fireRecordingStopped.bind(this))
; |
150 }, | 191 }, |
151 | 192 |
152 get records() | 193 /** |
| 194 * @return {!Array.<!WebInspector.TimelineModel.Record>} |
| 195 */ |
| 196 records: function() |
153 { | 197 { |
154 return this._records; | 198 return this._records; |
155 }, | 199 }, |
156 | 200 |
157 /** | 201 /** |
158 * @param {!WebInspector.Event} event | 202 * @param {!WebInspector.Event} event |
159 */ | 203 */ |
160 _onRecordAdded: function(event) | 204 _onRecordAdded: function(event) |
161 { | 205 { |
162 if (this._collectionEnabled) | 206 if (this._collectionEnabled) |
(...skipping 28 matching lines...) Expand all Loading... |
191 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStarted); | 235 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStarted); |
192 }, | 236 }, |
193 | 237 |
194 _fireRecordingStopped: function() | 238 _fireRecordingStopped: function() |
195 { | 239 { |
196 this._collectionEnabled = false; | 240 this._collectionEnabled = false; |
197 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStopped); | 241 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin
gStopped); |
198 }, | 242 }, |
199 | 243 |
200 /** | 244 /** |
201 * @param {!TimelineAgent.TimelineEvent} record | 245 * @param {!TimelineAgent.TimelineEvent} payload |
202 */ | 246 */ |
203 _addRecord: function(record) | 247 _addRecord: function(payload) |
204 { | 248 { |
205 this._internStringsAndAssignEndTime(record); | 249 this._internStrings(payload); |
| 250 this._payloads.push(payload); |
| 251 this._updateBoundaries(payload); |
| 252 |
| 253 var record = this._innerAddRecord(payload, null); |
206 this._records.push(record); | 254 this._records.push(record); |
207 this._updateBoundaries(record); | 255 |
208 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd
ded, record); | 256 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd
ded, record); |
209 }, | 257 }, |
210 | 258 |
211 /** | 259 /** |
| 260 * @param {!TimelineAgent.TimelineEvent} payload |
| 261 * @param {?WebInspector.TimelineModel.Record} parentRecord |
| 262 * @return {!WebInspector.TimelineModel.Record} |
| 263 * @this {!WebInspector.TimelineModel} |
| 264 */ |
| 265 _innerAddRecord: function(payload, parentRecord) |
| 266 { |
| 267 var record = new WebInspector.TimelineModel.Record(this, payload, parent
Record); |
| 268 for (var i = 0; payload.children && i < payload.children.length; ++i) |
| 269 this._innerAddRecord.call(this, payload.children[i], record); |
| 270 |
| 271 record.calculateAggregatedStats(); |
| 272 if (parentRecord) |
| 273 parentRecord._selfTime -= record.endTime - record.startTime; |
| 274 return record; |
| 275 }, |
| 276 |
| 277 /** |
212 * @param {!Blob} file | 278 * @param {!Blob} file |
213 * @param {!WebInspector.Progress} progress | 279 * @param {!WebInspector.Progress} progress |
214 */ | 280 */ |
215 loadFromFile: function(file, progress) | 281 loadFromFile: function(file, progress) |
216 { | 282 { |
217 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this,
progress); | 283 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this,
progress); |
218 var fileReader = this._createFileReader(file, delegate); | 284 var fileReader = this._createFileReader(file, delegate); |
219 var loader = new WebInspector.TimelineModelLoader(this, fileReader, prog
ress); | 285 var loader = new WebInspector.TimelineModelLoader(this, fileReader, prog
ress); |
220 fileReader.start(loader); | 286 fileReader.start(loader); |
221 }, | 287 }, |
(...skipping 27 matching lines...) Expand all Loading... |
249 | 315 |
250 /** | 316 /** |
251 * @param {boolean} accepted | 317 * @param {boolean} accepted |
252 * @this {WebInspector.TimelineModel} | 318 * @this {WebInspector.TimelineModel} |
253 */ | 319 */ |
254 function callback(accepted) | 320 function callback(accepted) |
255 { | 321 { |
256 if (!accepted) | 322 if (!accepted) |
257 return; | 323 return; |
258 var saver = new WebInspector.TimelineSaver(stream); | 324 var saver = new WebInspector.TimelineSaver(stream); |
259 saver.save(this._records, window.navigator.appVersion); | 325 saver.save(this._payloads, window.navigator.appVersion); |
260 } | 326 } |
261 stream.open(fileName, callback.bind(this)); | 327 stream.open(fileName, callback.bind(this)); |
262 }, | 328 }, |
263 | 329 |
264 reset: function() | 330 reset: function() |
265 { | 331 { |
266 this._records = []; | 332 this._records = []; |
| 333 this._payloads = []; |
267 this._stringPool = {}; | 334 this._stringPool = {}; |
268 this._minimumRecordTime = -1; | 335 this._minimumRecordTime = -1; |
269 this._maximumRecordTime = -1; | 336 this._maximumRecordTime = -1; |
| 337 this._bindings._reset(); |
270 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC
leared); | 338 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC
leared); |
271 }, | 339 }, |
272 | 340 |
273 /** | 341 /** |
274 * @return {number} | 342 * @return {number} |
275 */ | 343 */ |
276 minimumRecordTime: function() | 344 minimumRecordTime: function() |
277 { | 345 { |
278 return this._minimumRecordTime; | 346 return this._minimumRecordTime; |
279 }, | 347 }, |
(...skipping 25 matching lines...) Expand all Loading... |
305 * @return {number} | 373 * @return {number} |
306 */ | 374 */ |
307 recordOffsetInMillis: function(rawRecord) | 375 recordOffsetInMillis: function(rawRecord) |
308 { | 376 { |
309 return rawRecord.startTime - this._minimumRecordTime; | 377 return rawRecord.startTime - this._minimumRecordTime; |
310 }, | 378 }, |
311 | 379 |
312 /** | 380 /** |
313 * @param {!TimelineAgent.TimelineEvent} record | 381 * @param {!TimelineAgent.TimelineEvent} record |
314 */ | 382 */ |
315 _internStringsAndAssignEndTime: function(record) | 383 _internStrings: function(record) |
316 { | 384 { |
317 // We'd like to dump raw protocol in tests, so add an option to not assi
gn implicit end time. | |
318 if (!WebInspector.TimelineModel["_doNotAssignEndTime"]) { | |
319 if (typeof record.startTime === "number" && typeof record.endTime !=
= "number") | |
320 record.endTime = record.startTime; | |
321 } | |
322 | |
323 for (var name in record) { | 385 for (var name in record) { |
324 var value = record[name]; | 386 var value = record[name]; |
325 if (typeof value !== "string") | 387 if (typeof value !== "string") |
326 continue; | 388 continue; |
327 | 389 |
328 var interned = this._stringPool[value]; | 390 var interned = this._stringPool[value]; |
329 if (typeof interned === "string") | 391 if (typeof interned === "string") |
330 record[name] = interned; | 392 record[name] = interned; |
331 else | 393 else |
332 this._stringPool[value] = value; | 394 this._stringPool[value] = value; |
333 } | 395 } |
334 | 396 |
335 var children = record.children; | 397 var children = record.children; |
336 for (var i = 0; children && i < children.length; ++i) | 398 for (var i = 0; children && i < children.length; ++i) |
337 this._internStringsAndAssignEndTime(children[i]); | 399 this._internStrings(children[i]); |
338 }, | 400 }, |
339 | 401 |
340 __proto__: WebInspector.Object.prototype | 402 __proto__: WebInspector.Object.prototype |
341 } | 403 } |
342 | 404 |
| 405 |
| 406 /** |
| 407 * @constructor |
| 408 */ |
| 409 WebInspector.TimelineModel.InterRecordBindings = function() { |
| 410 this._reset(); |
| 411 } |
| 412 |
| 413 WebInspector.TimelineModel.InterRecordBindings.prototype = { |
| 414 _reset: function() |
| 415 { |
| 416 this._sendRequestRecords = {}; |
| 417 this._timerRecords = {}; |
| 418 this._requestAnimationFrameRecords = {}; |
| 419 this._layoutInvalidateStack = {}; |
| 420 this._lastScheduleStyleRecalculation = {}; |
| 421 this._webSocketCreateRecords = {}; |
| 422 } |
| 423 } |
| 424 |
| 425 /** |
| 426 * @constructor |
| 427 * @param {!WebInspector.TimelineModel} model |
| 428 * @param {!TimelineAgent.TimelineEvent} record |
| 429 * @param {?WebInspector.TimelineModel.Record} parentRecord |
| 430 */ |
| 431 WebInspector.TimelineModel.Record = function(model, record, parentRecord) |
| 432 { |
| 433 this._model = model; |
| 434 var bindings = this._model._bindings; |
| 435 this._aggregatedStats = {}; |
| 436 this._record = record; |
| 437 this._children = []; |
| 438 if (parentRecord) { |
| 439 this.parent = parentRecord; |
| 440 parentRecord.children.push(this); |
| 441 } |
| 442 |
| 443 this._selfTime = this.endTime - this.startTime; |
| 444 this._lastChildEndTime = this.endTime; |
| 445 this._startTimeOffset = this.startTime - model.minimumRecordTime(); |
| 446 |
| 447 if (record.data) { |
| 448 if (record.data["url"]) |
| 449 this.url = record.data["url"]; |
| 450 if (record.data["rootNode"]) |
| 451 this._relatedBackendNodeId = record.data["rootNode"]; |
| 452 else if (record.data["elementId"]) |
| 453 this._relatedBackendNodeId = record.data["elementId"]; |
| 454 if (record.data["scriptName"]) { |
| 455 this.scriptName = record.data["scriptName"]; |
| 456 this.scriptLine = record.data["scriptLine"]; |
| 457 } |
| 458 } |
| 459 |
| 460 if (parentRecord && parentRecord.callSiteStackTrace) |
| 461 this.callSiteStackTrace = parentRecord.callSiteStackTrace; |
| 462 |
| 463 var recordTypes = WebInspector.TimelineModel.RecordType; |
| 464 switch (record.type) { |
| 465 case recordTypes.ResourceSendRequest: |
| 466 // Make resource receive record last since request was sent; make finish
record last since response received. |
| 467 bindings._sendRequestRecords[record.data["requestId"]] = this; |
| 468 break; |
| 469 |
| 470 case recordTypes.ResourceReceiveResponse: |
| 471 var sendRequestRecord = bindings._sendRequestRecords[record.data["reques
tId"]]; |
| 472 if (sendRequestRecord) // False if we started instrumentation in the mid
dle of request. |
| 473 this.url = sendRequestRecord.url; |
| 474 break; |
| 475 |
| 476 case recordTypes.ResourceReceivedData: |
| 477 case recordTypes.ResourceFinish: |
| 478 var sendRequestRecord = bindings._sendRequestRecords[record.data["reques
tId"]]; |
| 479 if (sendRequestRecord) // False for main resource. |
| 480 this.url = sendRequestRecord.url; |
| 481 break; |
| 482 |
| 483 case recordTypes.TimerInstall: |
| 484 this.timeout = record.data["timeout"]; |
| 485 this.singleShot = record.data["singleShot"]; |
| 486 bindings._timerRecords[record.data["timerId"]] = this; |
| 487 break; |
| 488 |
| 489 case recordTypes.TimerFire: |
| 490 var timerInstalledRecord = bindings._timerRecords[record.data["timerId"]
]; |
| 491 if (timerInstalledRecord) { |
| 492 this.callSiteStackTrace = timerInstalledRecord.stackTrace; |
| 493 this.timeout = timerInstalledRecord.timeout; |
| 494 this.singleShot = timerInstalledRecord.singleShot; |
| 495 } |
| 496 break; |
| 497 |
| 498 case recordTypes.RequestAnimationFrame: |
| 499 bindings._requestAnimationFrameRecords[record.data["id"]] = this; |
| 500 break; |
| 501 |
| 502 case recordTypes.FireAnimationFrame: |
| 503 var requestAnimationRecord = bindings._requestAnimationFrameRecords[reco
rd.data["id"]]; |
| 504 if (requestAnimationRecord) |
| 505 this.callSiteStackTrace = requestAnimationRecord.stackTrace; |
| 506 break; |
| 507 |
| 508 case recordTypes.ConsoleTime: |
| 509 var message = record.data["message"]; |
| 510 break; |
| 511 |
| 512 case recordTypes.ScheduleStyleRecalculation: |
| 513 bindings._lastScheduleStyleRecalculation[this.frameId] = this; |
| 514 break; |
| 515 |
| 516 case recordTypes.RecalculateStyles: |
| 517 var scheduleStyleRecalculationRecord = bindings._lastScheduleStyleRecalc
ulation[this.frameId]; |
| 518 if (!scheduleStyleRecalculationRecord) |
| 519 break; |
| 520 this.callSiteStackTrace = scheduleStyleRecalculationRecord.stackTrace; |
| 521 break; |
| 522 |
| 523 case recordTypes.InvalidateLayout: |
| 524 // Consider style recalculation as a reason for layout invalidation, |
| 525 // but only if we had no earlier layout invalidation records. |
| 526 var styleRecalcStack; |
| 527 if (!bindings._layoutInvalidateStack[this.frameId]) { |
| 528 if (parentRecord.type === recordTypes.RecalculateStyles) |
| 529 styleRecalcStack = parentRecord.callSiteStackTrace; |
| 530 } |
| 531 bindings._layoutInvalidateStack[this.frameId] = styleRecalcStack || this
.stackTrace; |
| 532 break; |
| 533 |
| 534 case recordTypes.Layout: |
| 535 var layoutInvalidateStack = bindings._layoutInvalidateStack[this.frameId
]; |
| 536 if (layoutInvalidateStack) |
| 537 this.callSiteStackTrace = layoutInvalidateStack; |
| 538 if (this.stackTrace) |
| 539 this.addWarning(WebInspector.UIString("Forced synchronous layout is
a possible performance bottleneck.")); |
| 540 |
| 541 bindings._layoutInvalidateStack[this.frameId] = null; |
| 542 this.highlightQuad = record.data.root || WebInspector.TimelineModel._qua
dFromRectData(record.data); |
| 543 this._relatedBackendNodeId = record.data["rootNode"]; |
| 544 break; |
| 545 |
| 546 case recordTypes.AutosizeText: |
| 547 if (record.data.needsRelayout && parentRecord.type === recordTypes.Layou
t) |
| 548 parentRecord.addWarning(WebInspector.UIString("Layout required two p
asses due to text autosizing, consider setting viewport.")); |
| 549 break; |
| 550 |
| 551 case recordTypes.Paint: |
| 552 this.highlightQuad = record.data.clip || WebInspector.TimelineModel._qua
dFromRectData(record.data); |
| 553 break; |
| 554 |
| 555 case recordTypes.WebSocketCreate: |
| 556 this.webSocketURL = record.data["url"]; |
| 557 if (typeof record.data["webSocketProtocol"] !== "undefined") |
| 558 this.webSocketProtocol = record.data["webSocketProtocol"]; |
| 559 bindings._webSocketCreateRecords[record.data["identifier"]] = this; |
| 560 break; |
| 561 |
| 562 case recordTypes.WebSocketSendHandshakeRequest: |
| 563 case recordTypes.WebSocketReceiveHandshakeResponse: |
| 564 case recordTypes.WebSocketDestroy: |
| 565 var webSocketCreateRecord = bindings._webSocketCreateRecords[record.data
["identifier"]]; |
| 566 if (webSocketCreateRecord) { // False if we started instrumentation in t
he middle of request. |
| 567 this.webSocketURL = webSocketCreateRecord.webSocketURL; |
| 568 if (typeof webSocketCreateRecord.webSocketProtocol !== "undefined") |
| 569 this.webSocketProtocol = webSocketCreateRecord.webSocketProtocol
; |
| 570 } |
| 571 break; |
| 572 |
| 573 case recordTypes.EmbedderCallback: |
| 574 this.embedderCallbackName = record.data["callbackName"]; |
| 575 break; |
| 576 } |
| 577 } |
| 578 |
| 579 WebInspector.TimelineModel.Record.prototype = { |
| 580 get lastChildEndTime() |
| 581 { |
| 582 return this._lastChildEndTime; |
| 583 }, |
| 584 |
| 585 set lastChildEndTime(time) |
| 586 { |
| 587 this._lastChildEndTime = time; |
| 588 }, |
| 589 |
| 590 get selfTime() |
| 591 { |
| 592 return this._selfTime; |
| 593 }, |
| 594 |
| 595 get cpuTime() |
| 596 { |
| 597 return this._cpuTime; |
| 598 }, |
| 599 |
| 600 /** |
| 601 * @return {boolean} |
| 602 */ |
| 603 isRoot: function() |
| 604 { |
| 605 return this.type === WebInspector.TimelineModel.RecordType.Root; |
| 606 }, |
| 607 |
| 608 /** |
| 609 * @return {!Array.<!WebInspector.TimelineModel.Record>} |
| 610 */ |
| 611 get children() |
| 612 { |
| 613 return this._children; |
| 614 }, |
| 615 |
| 616 /** |
| 617 * @return {!WebInspector.TimelineCategory} |
| 618 */ |
| 619 get category() |
| 620 { |
| 621 return WebInspector.TimelineUIUtils.categoryForRecord(this); |
| 622 }, |
| 623 |
| 624 /** |
| 625 * @return {string} |
| 626 */ |
| 627 title: function() |
| 628 { |
| 629 return WebInspector.TimelineUIUtils.recordTitle(this); |
| 630 }, |
| 631 |
| 632 /** |
| 633 * @return {number} |
| 634 */ |
| 635 get startTime() |
| 636 { |
| 637 return this._startTime || this._record.startTime; |
| 638 }, |
| 639 |
| 640 set startTime(startTime) |
| 641 { |
| 642 this._startTime = startTime; |
| 643 }, |
| 644 |
| 645 /** |
| 646 * @return {string|undefined} |
| 647 */ |
| 648 get thread() |
| 649 { |
| 650 return this._record.thread; |
| 651 }, |
| 652 |
| 653 /** |
| 654 * @return {number} |
| 655 */ |
| 656 get startTimeOffset() |
| 657 { |
| 658 return this._startTimeOffset; |
| 659 }, |
| 660 |
| 661 /** |
| 662 * @return {number} |
| 663 */ |
| 664 get endTime() |
| 665 { |
| 666 return this._endTime || this._record.endTime || this._record.startTime; |
| 667 }, |
| 668 |
| 669 set endTime(endTime) |
| 670 { |
| 671 this._endTime = endTime; |
| 672 }, |
| 673 |
| 674 /** |
| 675 * @return {!Object} |
| 676 */ |
| 677 get data() |
| 678 { |
| 679 return this._record.data; |
| 680 }, |
| 681 |
| 682 /** |
| 683 * @return {string} |
| 684 */ |
| 685 get type() |
| 686 { |
| 687 return this._record.type; |
| 688 }, |
| 689 |
| 690 /** |
| 691 * @return {string} |
| 692 */ |
| 693 get frameId() |
| 694 { |
| 695 return this._record.frameId || ""; |
| 696 }, |
| 697 |
| 698 /** |
| 699 * @return {number} |
| 700 */ |
| 701 get usedHeapSizeDelta() |
| 702 { |
| 703 return this._record.usedHeapSizeDelta || 0; |
| 704 }, |
| 705 |
| 706 /** |
| 707 * @return {number} |
| 708 */ |
| 709 get jsHeapSizeUsed() |
| 710 { |
| 711 return this._record.counters ? this._record.counters.jsHeapSizeUsed || 0
: 0; |
| 712 }, |
| 713 |
| 714 /** |
| 715 * @return {!Object|undefined} |
| 716 */ |
| 717 get counters() |
| 718 { |
| 719 return this._record.counters; |
| 720 }, |
| 721 |
| 722 /** |
| 723 * @return {?Array.<!ConsoleAgent.CallFrame>} |
| 724 */ |
| 725 get stackTrace() |
| 726 { |
| 727 if (this._record.stackTrace && this._record.stackTrace.length) |
| 728 return this._record.stackTrace; |
| 729 return null; |
| 730 }, |
| 731 |
| 732 /** |
| 733 * @param {string} key |
| 734 * @return {?Object} |
| 735 */ |
| 736 getUserObject: function(key) |
| 737 { |
| 738 if (!this._userObjects) |
| 739 return null; |
| 740 return this._userObjects.get(key); |
| 741 }, |
| 742 |
| 743 /** |
| 744 * @param {string} key |
| 745 * @param {?Object|undefined} value |
| 746 */ |
| 747 setUserObject: function(key, value) |
| 748 { |
| 749 if (!this._userObjects) |
| 750 this._userObjects = new StringMap(); |
| 751 this._userObjects.put(key, value); |
| 752 }, |
| 753 |
| 754 /** |
| 755 * @return {number} nodeId |
| 756 */ |
| 757 relatedBackendNodeId: function() |
| 758 { |
| 759 return this._relatedBackendNodeId; |
| 760 }, |
| 761 |
| 762 calculateAggregatedStats: function() |
| 763 { |
| 764 this._aggregatedStats = {}; |
| 765 this._cpuTime = this._selfTime; |
| 766 |
| 767 for (var index = this._children.length; index; --index) { |
| 768 var child = this._children[index - 1]; |
| 769 for (var category in child._aggregatedStats) |
| 770 this._aggregatedStats[category] = (this._aggregatedStats[categor
y] || 0) + child._aggregatedStats[category]; |
| 771 } |
| 772 for (var category in this._aggregatedStats) |
| 773 this._cpuTime += this._aggregatedStats[category]; |
| 774 this._aggregatedStats[this.category.name] = (this._aggregatedStats[this.
category.name] || 0) + this._selfTime; |
| 775 }, |
| 776 |
| 777 get aggregatedStats() |
| 778 { |
| 779 return this._aggregatedStats; |
| 780 }, |
| 781 |
| 782 /** |
| 783 * @param {string} message |
| 784 */ |
| 785 addWarning: function(message) |
| 786 { |
| 787 if (this._warnings) |
| 788 this._warnings.push(message); |
| 789 else |
| 790 this._warnings = [message]; |
| 791 }, |
| 792 |
| 793 /** |
| 794 * @return {!Object} |
| 795 */ |
| 796 warnings: function() |
| 797 { |
| 798 return this._warnings; |
| 799 }, |
| 800 |
| 801 /** |
| 802 * @param {!RegExp} regExp |
| 803 * @return {boolean} |
| 804 */ |
| 805 testContentMatching: function(regExp) |
| 806 { |
| 807 var tokens = [this.title()]; |
| 808 for (var key in this._record.data) |
| 809 tokens.push(this._record.data[key]) |
| 810 return regExp.test(tokens.join("|")); |
| 811 } |
| 812 } |
| 813 |
343 /** | 814 /** |
344 * @constructor | 815 * @constructor |
345 * @implements {WebInspector.OutputStream} | 816 * @implements {WebInspector.OutputStream} |
346 * @param {!WebInspector.TimelineModel} model | 817 * @param {!WebInspector.TimelineModel} model |
347 * @param {!{cancel: function()}} reader | 818 * @param {!{cancel: function()}} reader |
348 * @param {!WebInspector.Progress} progress | 819 * @param {!WebInspector.Progress} progress |
349 */ | 820 */ |
350 WebInspector.TimelineModelLoader = function(model, reader, progress) | 821 WebInspector.TimelineModelLoader = function(model, reader, progress) |
351 { | 822 { |
352 this._model = model; | 823 this._model = model; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 /** | 943 /** |
473 * @constructor | 944 * @constructor |
474 */ | 945 */ |
475 WebInspector.TimelineSaver = function(stream) | 946 WebInspector.TimelineSaver = function(stream) |
476 { | 947 { |
477 this._stream = stream; | 948 this._stream = stream; |
478 } | 949 } |
479 | 950 |
480 WebInspector.TimelineSaver.prototype = { | 951 WebInspector.TimelineSaver.prototype = { |
481 /** | 952 /** |
482 * @param {!Array.<*>} records | 953 * @param {!Array.<*>} payloads |
483 * @param {string} version | 954 * @param {string} version |
484 */ | 955 */ |
485 save: function(records, version) | 956 save: function(payloads, version) |
486 { | 957 { |
487 this._records = records; | 958 this._payloads = payloads; |
488 this._recordIndex = 0; | 959 this._recordIndex = 0; |
489 this._prologue = "[" + JSON.stringify(version); | 960 this._prologue = "[" + JSON.stringify(version); |
490 | 961 |
491 this._writeNextChunk(this._stream); | 962 this._writeNextChunk(this._stream); |
492 }, | 963 }, |
493 | 964 |
494 _writeNextChunk: function(stream) | 965 _writeNextChunk: function(stream) |
495 { | 966 { |
496 const separator = ",\n"; | 967 const separator = ",\n"; |
497 var data = []; | 968 var data = []; |
498 var length = 0; | 969 var length = 0; |
499 | 970 |
500 if (this._prologue) { | 971 if (this._prologue) { |
501 data.push(this._prologue); | 972 data.push(this._prologue); |
502 length += this._prologue.length; | 973 length += this._prologue.length; |
503 delete this._prologue; | 974 delete this._prologue; |
504 } else { | 975 } else { |
505 if (this._recordIndex === this._records.length) { | 976 if (this._recordIndex === this._payloads.length) { |
506 stream.close(); | 977 stream.close(); |
507 return; | 978 return; |
508 } | 979 } |
509 data.push(""); | 980 data.push(""); |
510 } | 981 } |
511 while (this._recordIndex < this._records.length) { | 982 while (this._recordIndex < this._payloads.length) { |
512 var item = JSON.stringify(this._records[this._recordIndex]); | 983 var item = JSON.stringify(this._payloads[this._recordIndex]); |
513 var itemLength = item.length + separator.length; | 984 var itemLength = item.length + separator.length; |
514 if (length + itemLength > WebInspector.TimelineModel.TransferChunkLe
ngthBytes) | 985 if (length + itemLength > WebInspector.TimelineModel.TransferChunkLe
ngthBytes) |
515 break; | 986 break; |
516 length += itemLength; | 987 length += itemLength; |
517 data.push(item); | 988 data.push(item); |
518 ++this._recordIndex; | 989 ++this._recordIndex; |
519 } | 990 } |
520 if (this._recordIndex === this._records.length) | 991 if (this._recordIndex === this._payloads.length) |
521 data.push(data.pop() + "]"); | 992 data.push(data.pop() + "]"); |
522 stream.write(data.join(separator), this._writeNextChunk.bind(this)); | 993 stream.write(data.join(separator), this._writeNextChunk.bind(this)); |
523 } | 994 } |
524 } | 995 } |
525 | 996 |
526 /** | 997 /** |
527 * @constructor | 998 * @constructor |
528 */ | 999 */ |
529 WebInspector.TimelineMergingRecordBuffer = function() | 1000 WebInspector.TimelineMergingRecordBuffer = function() |
530 { | 1001 { |
(...skipping 21 matching lines...) Expand all Loading... |
552 */ | 1023 */ |
553 function recordTimestampComparator(a, b) | 1024 function recordTimestampComparator(a, b) |
554 { | 1025 { |
555 // Never return 0, as the merge function will squash identical entri
es. | 1026 // Never return 0, as the merge function will squash identical entri
es. |
556 return a.startTime < b.startTime ? -1 : 1; | 1027 return a.startTime < b.startTime ? -1 : 1; |
557 } | 1028 } |
558 var result = this._backgroundRecordsBuffer.mergeOrdered(records, recordT
imestampComparator); | 1029 var result = this._backgroundRecordsBuffer.mergeOrdered(records, recordT
imestampComparator); |
559 this._backgroundRecordsBuffer = []; | 1030 this._backgroundRecordsBuffer = []; |
560 return result; | 1031 return result; |
561 } | 1032 } |
562 }; | 1033 } |
| 1034 |
| 1035 /** |
| 1036 * @param {!Object} data |
| 1037 * @return {?Array.<number>} |
| 1038 */ |
| 1039 WebInspector.TimelineModel._quadFromRectData = function(data) |
| 1040 { |
| 1041 if (typeof data["x"] === "undefined" || typeof data["y"] === "undefined") |
| 1042 return null; |
| 1043 var x0 = data["x"]; |
| 1044 var x1 = data["x"] + data["width"]; |
| 1045 var y0 = data["y"]; |
| 1046 var y1 = data["y"] + data["height"]; |
| 1047 return [x0, y0, x1, y0, x1, y1, x0, y1]; |
| 1048 } |
OLD | NEW |