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

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

Issue 715803002: DevTools: merge TracingTimelineModel into TimelineModel (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 1 month 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
OLDNEW
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 12 matching lines...) Expand all
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
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 * @param {!WebInspector.TracingManager} tracingManager
34 * @param {!WebInspector.TracingModel} tracingModel
35 * @param {!WebInspector.TimelineModel.Filter} recordFilter
33 * @extends {WebInspector.Object} 36 * @extends {WebInspector.Object}
34 */ 37 */
35 WebInspector.TimelineModel = function() 38 WebInspector.TimelineModel = function(tracingManager, tracingModel, recordFilter )
36 { 39 {
37 WebInspector.Object.call(this); 40 WebInspector.Object.call(this);
38 this._filters = []; 41 this._filters = [];
42 this._tracingManager = tracingManager;
43 this._tracingModel = tracingModel;
44 this._recordFilter = recordFilter;
45 this._tracingManager.addEventListener(WebInspector.TracingManager.Events.Tra cingStarted, this._onTracingStarted, this);
46 this._tracingManager.addEventListener(WebInspector.TracingManager.Events.Eve ntsCollected, this._onEventsCollected, this);
47 this._tracingManager.addEventListener(WebInspector.TracingManager.Events.Tra cingComplete, this._onTracingComplete, this);
48 this.reset();
39 } 49 }
40 50
41 WebInspector.TimelineModel.RecordType = { 51 WebInspector.TimelineModel.RecordType = {
42 Root: "Root",
43 Program: "Program", 52 Program: "Program",
44 EventDispatch: "EventDispatch", 53 EventDispatch: "EventDispatch",
45 54
46 GPUTask: "GPUTask", 55 GPUTask: "GPUTask",
47 56
48 RequestMainThreadFrame: "RequestMainThreadFrame", 57 RequestMainThreadFrame: "RequestMainThreadFrame",
49 BeginFrame: "BeginFrame", 58 BeginFrame: "BeginFrame",
59 BeginMainThreadFrame: "BeginMainThreadFrame",
50 ActivateLayerTree: "ActivateLayerTree", 60 ActivateLayerTree: "ActivateLayerTree",
51 DrawFrame: "DrawFrame", 61 DrawFrame: "DrawFrame",
52 ScheduleStyleRecalculation: "ScheduleStyleRecalculation", 62 ScheduleStyleRecalculation: "ScheduleStyleRecalculation",
53 RecalculateStyles: "RecalculateStyles", 63 RecalculateStyles: "RecalculateStyles",
54 InvalidateLayout: "InvalidateLayout", 64 InvalidateLayout: "InvalidateLayout",
55 Layout: "Layout", 65 Layout: "Layout",
66 UpdateLayer: "UpdateLayer",
56 UpdateLayerTree: "UpdateLayerTree", 67 UpdateLayerTree: "UpdateLayerTree",
57 PaintSetup: "PaintSetup", 68 PaintSetup: "PaintSetup",
58 Paint: "Paint", 69 Paint: "Paint",
70 PaintImage: "PaintImage",
59 Rasterize: "Rasterize", 71 Rasterize: "Rasterize",
72 RasterTask: "RasterTask",
60 ScrollLayer: "ScrollLayer", 73 ScrollLayer: "ScrollLayer",
61 DecodeImage: "DecodeImage",
62 ResizeImage: "ResizeImage",
63 CompositeLayers: "CompositeLayers", 74 CompositeLayers: "CompositeLayers",
64 75
76 StyleRecalcInvalidationTracking: "StyleRecalcInvalidationTracking",
77 LayoutInvalidationTracking: "LayoutInvalidationTracking",
78 LayerInvalidationTracking: "LayerInvalidationTracking",
79 PaintInvalidationTracking: "PaintInvalidationTracking",
80
65 ParseHTML: "ParseHTML", 81 ParseHTML: "ParseHTML",
66 82
67 TimerInstall: "TimerInstall", 83 TimerInstall: "TimerInstall",
68 TimerRemove: "TimerRemove", 84 TimerRemove: "TimerRemove",
69 TimerFire: "TimerFire", 85 TimerFire: "TimerFire",
70 86
71 XHRReadyStateChange: "XHRReadyStateChange", 87 XHRReadyStateChange: "XHRReadyStateChange",
72 XHRLoad: "XHRLoad", 88 XHRLoad: "XHRLoad",
73 EvaluateScript: "EvaluateScript", 89 EvaluateScript: "EvaluateScript",
74 90
75 MarkLoad: "MarkLoad", 91 MarkLoad: "MarkLoad",
76 MarkDOMContent: "MarkDOMContent", 92 MarkDOMContent: "MarkDOMContent",
77 MarkFirstPaint: "MarkFirstPaint", 93 MarkFirstPaint: "MarkFirstPaint",
78 94
79 TimeStamp: "TimeStamp", 95 TimeStamp: "TimeStamp",
80 ConsoleTime: "ConsoleTime", 96 ConsoleTime: "ConsoleTime",
81 97
82 ResourceSendRequest: "ResourceSendRequest", 98 ResourceSendRequest: "ResourceSendRequest",
83 ResourceReceiveResponse: "ResourceReceiveResponse", 99 ResourceReceiveResponse: "ResourceReceiveResponse",
84 ResourceReceivedData: "ResourceReceivedData", 100 ResourceReceivedData: "ResourceReceivedData",
85 ResourceFinish: "ResourceFinish", 101 ResourceFinish: "ResourceFinish",
86 102
87 FunctionCall: "FunctionCall", 103 FunctionCall: "FunctionCall",
88 GCEvent: "GCEvent", 104 GCEvent: "GCEvent",
105 JSFrame: "JSFrame",
106 JSSample: "JSSample",
89 107
90 UpdateCounters: "UpdateCounters", 108 UpdateCounters: "UpdateCounters",
91 109
92 RequestAnimationFrame: "RequestAnimationFrame", 110 RequestAnimationFrame: "RequestAnimationFrame",
93 CancelAnimationFrame: "CancelAnimationFrame", 111 CancelAnimationFrame: "CancelAnimationFrame",
94 FireAnimationFrame: "FireAnimationFrame", 112 FireAnimationFrame: "FireAnimationFrame",
95 113
96 WebSocketCreate : "WebSocketCreate", 114 WebSocketCreate : "WebSocketCreate",
97 WebSocketSendHandshakeRequest : "WebSocketSendHandshakeRequest", 115 WebSocketSendHandshakeRequest : "WebSocketSendHandshakeRequest",
98 WebSocketReceiveHandshakeResponse : "WebSocketReceiveHandshakeResponse", 116 WebSocketReceiveHandshakeResponse : "WebSocketReceiveHandshakeResponse",
99 WebSocketDestroy : "WebSocketDestroy", 117 WebSocketDestroy : "WebSocketDestroy",
100 118
101 EmbedderCallback : "EmbedderCallback", 119 EmbedderCallback : "EmbedderCallback",
120
121 CallStack: "CallStack",
122 SetLayerTreeId: "SetLayerTreeId",
123 TracingStartedInPage: "TracingStartedInPage",
124 TracingSessionIdForWorker: "TracingSessionIdForWorker",
125
126 DecodeImage: "Decode Image",
127 ResizeImage: "Resize Image",
128 DrawLazyPixelRef: "Draw LazyPixelRef",
129 DecodeLazyPixelRef: "Decode LazyPixelRef",
130
131 LazyPixelRef: "LazyPixelRef",
132 LayerTreeHostImplSnapshot: "cc::LayerTreeHostImpl",
133 PictureSnapshot: "cc::Picture",
134
135 // CpuProfile is a virtual event created on frontend to support
136 // serialization of CPU Profiles within tracing timeline data.
137 CpuProfile: "CpuProfile"
102 } 138 }
103 139
104 WebInspector.TimelineModel.Events = { 140 WebInspector.TimelineModel.Events = {
105 RecordsCleared: "RecordsCleared", 141 RecordsCleared: "RecordsCleared",
106 RecordingStarted: "RecordingStarted", 142 RecordingStarted: "RecordingStarted",
107 RecordingStopped: "RecordingStopped", 143 RecordingStopped: "RecordingStopped",
108 RecordFilterChanged: "RecordFilterChanged" 144 RecordFilterChanged: "RecordFilterChanged"
109 } 145 }
110 146
111 WebInspector.TimelineModel.MainThreadName = "main"; 147 WebInspector.TimelineModel.MainThreadName = "main";
(...skipping 22 matching lines...) Expand all
134 if (postOrderCallback && postOrderCallback(record, depth)) 170 if (postOrderCallback && postOrderCallback(record, depth))
135 return true; 171 return true;
136 } 172 }
137 return false; 173 return false;
138 } 174 }
139 return processRecords(recordsArray, 0); 175 return processRecords(recordsArray, 0);
140 } 176 }
141 177
142 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; 178 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000;
143 179
180 /**
181 * @constructor
182 * @param {string} name
183 */
184 WebInspector.TimelineModel.VirtualThread = function(name)
185 {
186 this.name = name;
187 /** @type {!Array.<!WebInspector.TracingModel.Event>} */
188 this.events = [];
189 /** @type {!Array.<!Array.<!WebInspector.TracingModel.Event>>} */
190 this.asyncEvents = [];
191 }
192
193 /**
194 * @constructor
195 * @param {!WebInspector.TimelineModel} model
196 * @param {!WebInspector.TracingModel.Event} traceEvent
197 */
198 WebInspector.TimelineModel.Record = function(model, traceEvent)
199 {
200 this._model = model;
201 this._event = traceEvent;
202 traceEvent._timelineRecord = this;
203 this._children = [];
204 }
205
206 WebInspector.TimelineModel.Record.prototype = {
207 /**
208 * @return {?Array.<!ConsoleAgent.CallFrame>}
209 */
210 callSiteStackTrace: function()
211 {
212 var initiator = this._event.initiator;
213 return initiator ? initiator.stackTrace : null;
214 },
215
216 /**
217 * @return {?WebInspector.TimelineModel.Record}
218 */
219 initiator: function()
220 {
221 var initiator = this._event.initiator;
222 return initiator ? initiator._timelineRecord : null;
223 },
224
225 /**
226 * @return {?WebInspector.Target}
227 */
228 target: function()
229 {
230 return this._event.thread.target();
231 },
232
233 /**
234 * @return {number}
235 */
236 selfTime: function()
237 {
238 return this._event.selfTime;
239 },
240
241 /**
242 * @return {!Array.<!WebInspector.TimelineModel.Record>}
243 */
244 children: function()
245 {
246 return this._children;
247 },
248
249 /**
250 * @return {number}
251 */
252 startTime: function()
253 {
254 return this._event.startTime;
255 },
256
257 /**
258 * @return {string}
259 */
260 thread: function()
261 {
262 if (this._event.thread.name() === "CrRendererMain")
263 return WebInspector.TimelineModel.MainThreadName;
264 return this._event.thread.name();
265 },
266
267 /**
268 * @return {number}
269 */
270 endTime: function()
271 {
272 return this._endTime || this._event.endTime || this._event.startTime;
273 },
274
275 /**
276 * @param {number} endTime
277 */
278 setEndTime: function(endTime)
279 {
280 this._endTime = endTime;
281 },
282
283 /**
284 * @return {!Object}
285 */
286 data: function()
287 {
288 return this._event.args["data"];
289 },
290
291 /**
292 * @return {string}
293 */
294 type: function()
295 {
296 if (this._event.category === WebInspector.TracingModel.ConsoleEventCateg ory)
297 return WebInspector.TimelineModel.RecordType.ConsoleTime;
298 return this._event.name;
299 },
300
301 /**
302 * @return {string}
303 */
304 frameId: function()
305 {
306 switch (this._event.name) {
307 case WebInspector.TimelineModel.RecordType.ScheduleStyleRecalculation:
308 case WebInspector.TimelineModel.RecordType.RecalculateStyles:
309 case WebInspector.TimelineModel.RecordType.InvalidateLayout:
310 return this._event.args["frameId"];
311 case WebInspector.TimelineModel.RecordType.Layout:
312 return this._event.args["beginData"]["frameId"];
313 default:
314 var data = this._event.args["data"];
315 return (data && data["frame"]) || "";
316 }
317 },
318
319 /**
320 * @return {?Array.<!ConsoleAgent.CallFrame>}
321 */
322 stackTrace: function()
323 {
324 return this._event.stackTrace;
325 },
326
327 /**
328 * @param {string} key
329 * @return {?Object}
330 */
331 getUserObject: function(key)
332 {
333 if (key === "TimelineUIUtils::preview-element")
334 return this._event.previewElement;
335 throw new Error("Unexpected key: " + key);
336 },
337
338 /**
339 * @param {string} key
340 * @param {?Object|undefined} value
341 */
342 setUserObject: function(key, value)
343 {
344 if (key !== "TimelineUIUtils::preview-element")
345 throw new Error("Unexpected key: " + key);
346 this._event.previewElement = /** @type {?Element} */ (value);
347 },
348
349 /**
350 * @return {?Array.<string>}
351 */
352 warnings: function()
353 {
354 if (this._event.warning)
355 return [this._event.warning];
356 return null;
357 },
358
359 /**
360 * @return {!WebInspector.TracingModel.Event}
361 */
362 traceEvent: function()
363 {
364 return this._event;
365 },
366
367 /**
368 * @param {!WebInspector.TimelineModel.Record} child
369 */
370 _addChild: function(child)
371 {
372 this._children.push(child);
373 child.parent = this;
374 },
375
376 /**
377 * @return {!WebInspector.TimelineModel}
378 */
379 timelineModel: function()
380 {
381 return this._model;
382 }
383 }
384
144 WebInspector.TimelineModel.prototype = { 385 WebInspector.TimelineModel.prototype = {
145 /** 386 /**
146 * @param {boolean} captureCauses 387 * @param {boolean} captureCauses
388 * @param {boolean} enableJSSampling
147 * @param {boolean} captureMemory 389 * @param {boolean} captureMemory
148 * @param {boolean} capturePictures 390 * @param {boolean} capturePictures
149 */ 391 */
150 startRecording: function(captureCauses, captureMemory, capturePictures) 392 startRecording: function(captureCauses, enableJSSampling, captureMemory, cap turePictures)
151 { 393 {
394 function disabledByDefault(category)
395 {
396 return "disabled-by-default-" + category;
397 }
398 var categoriesArray = [
399 "-*",
400 disabledByDefault("devtools.timeline"),
401 disabledByDefault("devtools.timeline.frame"),
402 WebInspector.TracingModel.ConsoleEventCategory
403 ];
404 if (captureCauses || enableJSSampling)
405 categoriesArray.push(disabledByDefault("devtools.timeline.stack"));
406 if (enableJSSampling)
407 this._startCpuProfilingOnAllTargets();
408 if (captureCauses && Runtime.experiments.isEnabled("timelineInvalidation Tracking"))
409 categoriesArray.push(disabledByDefault("devtools.timeline.invalidati onTracking"));
410 if (capturePictures) {
411 categoriesArray = categoriesArray.concat([
412 disabledByDefault("devtools.timeline.layers"),
413 disabledByDefault("devtools.timeline.picture"),
414 disabledByDefault("blink.graphics_context_annotations")]);
415 }
416 var categories = categoriesArray.join(",");
417 this._startRecordingWithCategories(categories);
152 }, 418 },
153 419
154 stopRecording: function() 420 stopRecording: function()
155 { 421 {
156 }, 422 this._stopCallbackBarrier = new CallbackBarrier();
157 423 this._stopProfilingOnAllTargets();
158 /** 424 this._tracingManager.stop();
425 },
426
427 /**
159 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspe ctor.TimelineModel.Record,number)} preOrderCallback 428 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspe ctor.TimelineModel.Record,number)} preOrderCallback
160 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect or.TimelineModel.Record,number)=} postOrderCallback 429 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect or.TimelineModel.Record,number)=} postOrderCallback
161 */ 430 */
162 forAllRecords: function(preOrderCallback, postOrderCallback) 431 forAllRecords: function(preOrderCallback, postOrderCallback)
163 { 432 {
164 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback , postOrderCallback); 433 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback , postOrderCallback);
165 }, 434 },
166 435
167 /** 436 /**
168 * @param {!WebInspector.TimelineModel.Filter} filter 437 * @param {!WebInspector.TimelineModel.Filter} filter
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 492
224 /** 493 /**
225 * @return {!Array.<!WebInspector.TimelineModel.Record>} 494 * @return {!Array.<!WebInspector.TimelineModel.Record>}
226 */ 495 */
227 records: function() 496 records: function()
228 { 497 {
229 return this._records; 498 return this._records;
230 }, 499 },
231 500
232 /** 501 /**
502 * @param {!Array.<!WebInspector.TracingManager.EventPayload>} events
503 */
504 setEventsForTest: function(events)
505 {
506 this._startCollectingTraceEvents(false);
507 this._tracingModel.addEvents(events);
508 this._onTracingComplete();
509 },
510
511 _startCpuProfilingOnAllTargets: function()
512 {
513 this._profilingTargets = WebInspector.targetManager.targets();
514 for (var i = 0; i < this._profilingTargets.length; ++i) {
515 var target = this._profilingTargets[i];
516 this._configureCpuProfilerSamplingInterval(target);
517 target.profilerAgent().start();
518 }
519 },
520
521 _stopProfilingOnAllTargets: function()
522 {
523 if (!this._profilingTargets)
524 return;
525 for (var i = 0; i < this._profilingTargets.length; ++i) {
526 var target = this._profilingTargets[i];
527 target.profilerAgent().stop(this._stopCallbackBarrier.createCallback (this._didStopRecordingJSSamples.bind(this, target)));
528 }
529 this._profilingTargets = null;
530 },
531
532 /**
533 * @param {!WebInspector.Target} target
534 */
535 _configureCpuProfilerSamplingInterval: function(target)
536 {
537 var intervalUs = WebInspector.settings.highResolutionCpuProfiling.get() ? 100 : 1000;
538 target.profilerAgent().setSamplingInterval(intervalUs, didChangeInterval );
539
540 function didChangeInterval(error)
541 {
542 if (error)
543 WebInspector.console.error(error);
544 }
545 },
546
547 /**
548 * @param {string} categories
549 */
550 _startRecordingWithCategories: function(categories)
551 {
552 this._tracingManager.start(categories, "");
553 },
554
555 _onTracingStarted: function()
556 {
557 this._startCollectingTraceEvents(false);
558 },
559
560 /**
561 * @param {boolean} fromFile
562 */
563 _startCollectingTraceEvents: function(fromFile)
564 {
565 this.reset();
566 this._tracingModel.reset();
567 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStarted, { fromFile: fromFile });
568 },
569
570 /**
571 * @param {!WebInspector.Event} event
572 */
573 _onEventsCollected: function(event)
574 {
575 var traceEvents = /** @type {!Array.<!WebInspector.TracingManager.EventP ayload>} */ (event.data);
576 this._tracingModel.addEvents(traceEvents);
577 },
578
579 _onTracingComplete: function()
580 {
581 if (this._stopCallbackBarrier) {
582 this._stopCallbackBarrier.callWhenDone(this._didStopRecordingTraceEv ents.bind(this));
583 this._stopCallbackBarrier = null;
584 } else {
585 this._didStopRecordingTraceEvents();
586 }
587 },
588
589 /**
590 * @param {!WebInspector.Target} target
591 * @param {?Protocol.Error} error
592 * @param {?ProfilerAgent.CPUProfile} cpuProfile
593 */
594 _didStopRecordingJSSamples: function(target, error, cpuProfile)
595 {
596 if (error)
597 WebInspector.console.error(error);
598 if (!this._cpuProfiles)
599 this._cpuProfiles = {};
600 this._cpuProfiles[target.id()] = cpuProfile;
601 },
602
603 _didStopRecordingTraceEvents: function()
604 {
605 this._tracingModel.tracingComplete();
606
607 var events = this._tracingModel.devtoolsPageMetadataEvents();
608 var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEven ts();
609
610 this._resetProcessingState();
611 for (var i = 0, length = events.length; i < length; i++) {
612 var event = events[i];
613 var process = event.thread.process();
614 var startTime = event.startTime;
615
616 var endTime = Infinity;
617 if (i + 1 < length)
618 endTime = events[i + 1].startTime;
619
620 var threads = process.sortedThreads();
621 for (var j = 0; j < threads.length; j++) {
622 var thread = threads[j];
623 if (thread.name() === "WebCore: Worker" && workerMetadataEvents. every(function(e) { return e.args["data"]["workerThreadId"] !== thread.id(); }))
624 continue;
625 this._processThreadEvents(startTime, endTime, event.thread, thre ad);
626 }
627 }
628 this._resetProcessingState();
629
630 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare StartTime);
631
632 this._cpuProfiles = null;
633
634 this._buildTimelineRecords();
635 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped);
636 },
637
638 /**
639 * @param {!ProfilerAgent.CPUProfile} cpuProfile
640 */
641 _injectCpuProfileEvent: function(cpuProfile)
642 {
643 var metaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast ();
644 if (!metaEvent)
645 return;
646 var cpuProfileEvent = /** @type {!WebInspector.TracingManager.EventPaylo ad} */ ({
647 cat: WebInspector.TracingModel.DevToolsMetadataEventCategory,
648 ph: WebInspector.TracingModel.Phase.Instant,
649 ts: this._tracingModel.maximumRecordTime() * 1000,
650 pid: metaEvent.thread.process().id(),
651 tid: metaEvent.thread.id(),
652 name: WebInspector.TimelineModel.RecordType.CpuProfile,
653 args: { data: { cpuProfile: cpuProfile } }
654 });
655 this._tracingModel.addEvents([cpuProfileEvent]);
656 },
657
658 _buildTimelineRecords: function()
659 {
660 var topLevelRecords = this._buildTimelineRecordsForThread(this.mainThrea dEvents());
661
662 /**
663 * @param {!WebInspector.TimelineModel.Record} a
664 * @param {!WebInspector.TimelineModel.Record} b
665 * @return {number}
666 */
667 function compareRecordStartTime(a, b)
668 {
669 // Never return 0 as otherwise equal records would be merged.
670 return (a.startTime() <= b.startTime()) ? -1 : +1;
671 }
672
673 /**
674 * @param {!WebInspector.TimelineModel.VirtualThread} virtualThread
675 * @this {!WebInspector.TimelineModel}
676 */
677 function processVirtualThreadEvents(virtualThread)
678 {
679 var threadRecords = this._buildTimelineRecordsForThread(virtualThrea d.events);
680 topLevelRecords = topLevelRecords.mergeOrdered(threadRecords, compar eRecordStartTime);
681 }
682 this.virtualThreads().forEach(processVirtualThreadEvents.bind(this));
683
684
685 for (var i = 0; i < topLevelRecords.length; i++) {
686 var record = topLevelRecords[i];
687 if (record.type() === WebInspector.TimelineModel.RecordType.Program)
688 this._mainThreadTasks.push(record);
689 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask)
690 this._gpuThreadTasks.push(record);
691 }
692 this._records = topLevelRecords;
693 },
694
695 /**
696 * @param {!Array.<!WebInspector.TracingModel.Event>} threadEvents
697 * @return {!Array.<!WebInspector.TimelineModel.Record>}
698 */
699 _buildTimelineRecordsForThread: function(threadEvents)
700 {
701 var recordStack = [];
702 var topLevelRecords = [];
703
704 for (var i = 0, size = threadEvents.length; i < size; ++i) {
705 var event = threadEvents[i];
706 for (var top = recordStack.peekLast(); top && top._event.endTime <= event.startTime; top = recordStack.peekLast()) {
707 recordStack.pop();
708 if (!recordStack.length)
709 topLevelRecords.push(top);
710 }
711 if (event.phase === WebInspector.TracingModel.Phase.AsyncEnd || even t.phase === WebInspector.TracingModel.Phase.NestableAsyncEnd)
712 continue;
713 var parentRecord = recordStack.peekLast();
714 // Maintain the back-end logic of old timeline, skip console.time() / console.timeEnd() that are not properly nested.
715 if (WebInspector.TracingModel.isAsyncBeginPhase(event.phase) && pare ntRecord && event.endTime > parentRecord._event.endTime)
716 continue;
717 var record = new WebInspector.TimelineModel.Record(this, event);
718 if (WebInspector.TimelineUIUtils.isMarkerEvent(event))
719 this._eventDividerRecords.push(record);
720 if (!this._recordFilter.accept(record))
721 continue;
722 if (parentRecord)
723 parentRecord._addChild(record);
724 if (event.endTime)
725 recordStack.push(record);
726 }
727
728 if (recordStack.length)
729 topLevelRecords.push(recordStack[0]);
730
731 return topLevelRecords;
732 },
733
734 _resetProcessingState: function()
735 {
736 this._sendRequestEvents = {};
737 this._timerEvents = {};
738 this._requestAnimationFrameEvents = {};
739 this._invalidationTracker = new WebInspector.InvalidationTracker();
740 this._layoutInvalidate = {};
741 this._lastScheduleStyleRecalculation = {};
742 this._webSocketCreateEvents = {};
743 this._paintImageEventByPixelRefId = {};
744 this._lastPaintForLayer = {};
745 this._lastRecalculateStylesEvent = null;
746 this._currentScriptEvent = null;
747 this._eventStack = [];
748 },
749
750 /**
751 * @param {number} startTime
752 * @param {?number} endTime
753 * @param {!WebInspector.TracingModel.Thread} mainThread
754 * @param {!WebInspector.TracingModel.Thread} thread
755 */
756 _processThreadEvents: function(startTime, endTime, mainThread, thread)
757 {
758 var events = thread.events();
759 var length = events.length;
760 var i = events.lowerBound(startTime, function (time, event) { return tim e - event.startTime });
761
762 var threadEvents;
763 var virtualThread = null;
764 if (thread === mainThread) {
765 threadEvents = this._mainThreadEvents;
766 this._mainThreadAsyncEvents = this._mainThreadAsyncEvents.concat(thr ead.asyncEvents());
767 } else {
768 virtualThread = new WebInspector.TimelineModel.VirtualThread(thread. name());
769 threadEvents = virtualThread.events;
770 virtualThread.asyncEvents = virtualThread.asyncEvents.concat(thread. asyncEvents());
771 this._virtualThreads.push(virtualThread);
772 }
773
774 this._eventStack = [];
775 for (; i < length; i++) {
776 var event = events[i];
777 if (endTime && event.startTime >= endTime)
778 break;
779 this._processEvent(event);
780 threadEvents.push(event);
781 this._inspectedTargetEvents.push(event);
782 }
783
784 if (this._cpuProfiles && thread.target()) {
785 var cpuProfile = this._cpuProfiles[thread.target().id()];
786 if (cpuProfile) {
787 var jsSamples = WebInspector.TimelineJSProfileProcessor.generate TracingEventsFromCpuProfile(cpuProfile, thread);
788 var mergedEvents = threadEvents.mergeOrdered(jsSamples, WebInspe ctor.TracingModel.Event.orderedCompareStartTime);
789 var jsFrameEvents = WebInspector.TimelineJSProfileProcessor.gene rateJSFrameEvents(mergedEvents);
790 mergedEvents = jsFrameEvents.mergeOrdered(mergedEvents, WebInspe ctor.TracingModel.Event.orderedCompareStartTime);
791 if (virtualThread)
792 virtualThread.events = mergedEvents;
793 else
794 this._mainThreadEvents = mergedEvents;
795 this._inspectedTargetEvents = this._inspectedTargetEvents.concat (jsSamples, jsFrameEvents);
796 }
797 }
798 },
799
800 /**
801 * @param {!WebInspector.TracingModel.Event} event
802 */
803 _processEvent: function(event)
804 {
805 var recordTypes = WebInspector.TimelineModel.RecordType;
806
807 var eventStack = this._eventStack;
808 while (eventStack.length && eventStack.peekLast().endTime < event.startT ime)
809 eventStack.pop();
810 var duration = event.duration;
811 if (duration) {
812 if (eventStack.length) {
813 var parent = eventStack.peekLast();
814 parent.selfTime -= duration;
815 }
816 event.selfTime = duration;
817 eventStack.push(event);
818 }
819
820 if (this._currentScriptEvent && event.startTime > this._currentScriptEve nt.endTime)
821 this._currentScriptEvent = null;
822
823 switch (event.name) {
824 case recordTypes.CallStack:
825 var lastMainThreadEvent = this.mainThreadEvents().peekLast();
826 if (lastMainThreadEvent && event.args["stack"] && event.args["stack" ].length)
827 lastMainThreadEvent.stackTrace = event.args["stack"];
828 break;
829
830 case recordTypes.CpuProfile:
831 this._cpuProfile = event.args["data"]["cpuProfile"];
832 break;
833
834 case recordTypes.ResourceSendRequest:
835 this._sendRequestEvents[event.args["data"]["requestId"]] = event;
836 event.imageURL = event.args["data"]["url"];
837 break;
838
839 case recordTypes.ResourceReceiveResponse:
840 case recordTypes.ResourceReceivedData:
841 case recordTypes.ResourceFinish:
842 event.initiator = this._sendRequestEvents[event.args["data"]["reques tId"]];
843 if (event.initiator)
844 event.imageURL = event.initiator.imageURL;
845 break;
846
847 case recordTypes.TimerInstall:
848 this._timerEvents[event.args["data"]["timerId"]] = event;
849 break;
850
851 case recordTypes.TimerFire:
852 event.initiator = this._timerEvents[event.args["data"]["timerId"]];
853 break;
854
855 case recordTypes.RequestAnimationFrame:
856 this._requestAnimationFrameEvents[event.args["data"]["id"]] = event;
857 break;
858
859 case recordTypes.FireAnimationFrame:
860 event.initiator = this._requestAnimationFrameEvents[event.args["data "]["id"]];
861 break;
862
863 case recordTypes.ScheduleStyleRecalculation:
864 this._lastScheduleStyleRecalculation[event.args["frame"]] = event;
865 break;
866
867 case recordTypes.RecalculateStyles:
868 this._invalidationTracker.didRecalcStyle(event);
869 event.initiator = this._lastScheduleStyleRecalculation[event.args["f rame"]];
870 this._lastRecalculateStylesEvent = event;
871 break;
872
873 case recordTypes.StyleRecalcInvalidationTracking:
874 case recordTypes.LayoutInvalidationTracking:
875 case recordTypes.LayerInvalidationTracking:
876 case recordTypes.PaintInvalidationTracking:
877 this._invalidationTracker.addInvalidation(event);
878 break;
879
880 case recordTypes.InvalidateLayout:
881 // Consider style recalculation as a reason for layout invalidation,
882 // but only if we had no earlier layout invalidation records.
883 var layoutInitator = event;
884 var frameId = event.args["frame"];
885 if (!this._layoutInvalidate[frameId] && this._lastRecalculateStylesE vent && this._lastRecalculateStylesEvent.endTime > event.startTime)
886 layoutInitator = this._lastRecalculateStylesEvent.initiator;
887 this._layoutInvalidate[frameId] = layoutInitator;
888 break;
889
890 case recordTypes.Layout:
891 this._invalidationTracker.didLayout(event);
892 var frameId = event.args["beginData"]["frame"];
893 event.initiator = this._layoutInvalidate[frameId];
894 // In case we have no closing Layout event, endData is not available .
895 if (event.args["endData"]) {
896 event.backendNodeId = event.args["endData"]["rootNode"];
897 event.highlightQuad = event.args["endData"]["root"];
898 }
899 this._layoutInvalidate[frameId] = null;
900 if (this._currentScriptEvent)
901 event.warning = WebInspector.UIString("Forced synchronous layout is a possible performance bottleneck.");
902 break;
903
904 case recordTypes.WebSocketCreate:
905 this._webSocketCreateEvents[event.args["data"]["identifier"]] = even t;
906 break;
907
908 case recordTypes.WebSocketSendHandshakeRequest:
909 case recordTypes.WebSocketReceiveHandshakeResponse:
910 case recordTypes.WebSocketDestroy:
911 event.initiator = this._webSocketCreateEvents[event.args["data"]["id entifier"]];
912 break;
913
914 case recordTypes.EvaluateScript:
915 case recordTypes.FunctionCall:
916 if (!this._currentScriptEvent)
917 this._currentScriptEvent = event;
918 break;
919
920 case recordTypes.SetLayerTreeId:
921 this._inspectedTargetLayerTreeId = event.args["layerTreeId"];
922 break;
923
924 case recordTypes.Paint:
925 this._invalidationTracker.didPaint(event);
926 event.highlightQuad = event.args["data"]["clip"];
927 event.backendNodeId = event.args["data"]["nodeId"];
928 var layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLay er);
929 if (!layerUpdateEvent || layerUpdateEvent.args["layerTreeId"] !== th is._inspectedTargetLayerTreeId)
930 break;
931 // Only keep layer paint events, skip paints for subframes that get painted to the same layer as parent.
932 if (!event.args["data"]["layerId"])
933 break;
934 this._lastPaintForLayer[layerUpdateEvent.args["layerId"]] = event;
935 break;
936
937 case recordTypes.PictureSnapshot:
938 var layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLay er);
939 if (!layerUpdateEvent || layerUpdateEvent.args["layerTreeId"] !== th is._inspectedTargetLayerTreeId)
940 break;
941 var paintEvent = this._lastPaintForLayer[layerUpdateEvent.args["laye rId"]];
942 if (paintEvent)
943 paintEvent.picture = event;
944 break;
945
946 case recordTypes.ScrollLayer:
947 event.backendNodeId = event.args["data"]["nodeId"];
948 break;
949
950 case recordTypes.PaintImage:
951 event.backendNodeId = event.args["data"]["nodeId"];
952 event.imageURL = event.args["data"]["url"];
953 break;
954
955 case recordTypes.DecodeImage:
956 case recordTypes.ResizeImage:
957 var paintImageEvent = this._findAncestorEvent(recordTypes.PaintImage );
958 if (!paintImageEvent) {
959 var decodeLazyPixelRefEvent = this._findAncestorEvent(recordType s.DecodeLazyPixelRef);
960 paintImageEvent = decodeLazyPixelRefEvent && this._paintImageEve ntByPixelRefId[decodeLazyPixelRefEvent.args["LazyPixelRef"]];
961 }
962 if (!paintImageEvent)
963 break;
964 event.backendNodeId = paintImageEvent.backendNodeId;
965 event.imageURL = paintImageEvent.imageURL;
966 break;
967
968 case recordTypes.DrawLazyPixelRef:
969 var paintImageEvent = this._findAncestorEvent(recordTypes.PaintImage );
970 if (!paintImageEvent)
971 break;
972 this._paintImageEventByPixelRefId[event.args["LazyPixelRef"]] = pain tImageEvent;
973 event.backendNodeId = paintImageEvent.backendNodeId;
974 event.imageURL = paintImageEvent.imageURL;
975 break;
976 }
977 },
978
979 /**
980 * @param {string} name
981 * @return {?WebInspector.TracingModel.Event}
982 */
983 _findAncestorEvent: function(name)
984 {
985 for (var i = this._eventStack.length - 1; i >= 0; --i) {
986 var event = this._eventStack[i];
987 if (event.name === name)
988 return event;
989 }
990 return null;
991 },
992
993 /**
233 * @param {!Blob} file 994 * @param {!Blob} file
234 * @param {!WebInspector.Progress} progress 995 * @param {!WebInspector.Progress} progress
235 */ 996 */
236 loadFromFile: function(file, progress) 997 loadFromFile: function(file, progress)
237 { 998 {
238 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress); 999 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress);
239 var fileReader = this._createFileReader(file, delegate); 1000 var fileReader = this._createFileReader(file, delegate);
240 var loader = this.createLoader(fileReader, progress); 1001 var loader = this.createLoader(fileReader, progress);
241 fileReader.start(loader); 1002 fileReader.start(loader);
242 }, 1003 },
243 1004
244 /**
245 * @param {!WebInspector.ChunkedFileReader} fileReader
246 * @param {!WebInspector.Progress} progress
247 * @return {!WebInspector.OutputStream}
248 */
249 createLoader: function(fileReader, progress)
250 {
251 throw new Error("Not implemented.");
252 },
253
254 _createFileReader: function(file, delegate) 1005 _createFileReader: function(file, delegate)
255 { 1006 {
256 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineMod el.TransferChunkLengthBytes, delegate); 1007 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineMod el.TransferChunkLengthBytes, delegate);
257 }, 1008 },
258 1009
259 _createFileWriter: function() 1010 _createFileWriter: function()
260 { 1011 {
261 return new WebInspector.FileOutputStream(); 1012 return new WebInspector.FileOutputStream();
262 }, 1013 },
263 1014
264 saveToFile: function() 1015 saveToFile: function()
265 { 1016 {
266 var now = new Date(); 1017 var now = new Date();
267 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; 1018 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json";
268 var stream = this._createFileWriter(); 1019 var stream = this._createFileWriter();
269 1020
270 /** 1021 /**
271 * @param {boolean} accepted 1022 * @param {boolean} accepted
272 * @this {WebInspector.TimelineModel} 1023 * @this {WebInspector.TimelineModel}
273 */ 1024 */
274 function callback(accepted) 1025 function callback(accepted)
275 { 1026 {
276 if (!accepted) 1027 if (!accepted)
277 return; 1028 return;
278 this.writeToStream(stream); 1029 this.writeToStream(stream);
279 } 1030 }
280 stream.open(fileName, callback.bind(this)); 1031 stream.open(fileName, callback.bind(this));
281 }, 1032 },
282 1033
283 /**
284 * @param {!WebInspector.OutputStream} stream
285 */
286 writeToStream: function(stream)
287 {
288 throw new Error("Not implemented.");
289 },
290
291 reset: function() 1034 reset: function()
292 { 1035 {
1036 this._virtualThreads = [];
1037 this._mainThreadEvents = [];
1038 this._mainThreadAsyncEvents = [];
1039 this._inspectedTargetEvents = [];
1040
293 this._records = []; 1041 this._records = [];
294 this._minimumRecordTime = 0;
295 this._maximumRecordTime = 0;
296 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 1042 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
297 this._mainThreadTasks = []; 1043 this._mainThreadTasks = [];
298 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 1044 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
299 this._gpuThreadTasks = []; 1045 this._gpuThreadTasks = [];
300 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 1046 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
301 this._eventDividerRecords = []; 1047 this._eventDividerRecords = [];
302 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC leared); 1048 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC leared);
303 }, 1049 },
304 1050
305 /** 1051 /**
306 * @return {number} 1052 * @return {number}
307 */ 1053 */
308 minimumRecordTime: function() 1054 minimumRecordTime: function()
309 { 1055 {
310 throw new Error("Not implemented."); 1056 return this._tracingModel.minimumRecordTime();
311 }, 1057 },
312 1058
313 /** 1059 /**
314 * @return {number} 1060 * @return {number}
315 */ 1061 */
316 maximumRecordTime: function() 1062 maximumRecordTime: function()
317 { 1063 {
318 throw new Error("Not implemented."); 1064 return this._tracingModel.maximumRecordTime();
1065 },
1066
1067 /**
1068 * @return {!Array.<!WebInspector.TracingModel.Event>}
1069 */
1070 inspectedTargetEvents: function()
1071 {
1072 return this._inspectedTargetEvents;
1073 },
1074
1075 /**
1076 * @return {!Array.<!WebInspector.TracingModel.Event>}
1077 */
1078 mainThreadEvents: function()
1079 {
1080 return this._mainThreadEvents;
1081 },
1082
1083 /**
1084 * @param {!Array.<!WebInspector.TracingModel.Event>} events
1085 */
1086 _setMainThreadEvents: function(events)
1087 {
1088 this._mainThreadEvents = events;
1089 },
1090
1091 /**
1092 * @return {!Array.<!Array.<!WebInspector.TracingModel.Event>>}
1093 */
1094 mainThreadAsyncEvents: function()
1095 {
1096 return this._mainThreadAsyncEvents;
1097 },
1098
1099 /**
1100 * @return {!Array.<!WebInspector.TimelineModel.VirtualThread>}
1101 */
1102 virtualThreads: function()
1103 {
1104 return this._virtualThreads;
1105 },
1106
1107 /**
1108 * @param {!WebInspector.ChunkedFileReader} fileReader
1109 * @param {!WebInspector.Progress} progress
1110 * @return {!WebInspector.OutputStream}
1111 */
1112 createLoader: function(fileReader, progress)
1113 {
1114 return new WebInspector.TracingModelLoader(this, fileReader, progress);
1115 },
1116
1117 /**
1118 * @param {!WebInspector.OutputStream} stream
1119 */
1120 writeToStream: function(stream)
1121 {
1122 var saver = new WebInspector.TracingTimelineSaver(stream);
1123 this._tracingModel.writeToStream(stream, saver);
319 }, 1124 },
320 1125
321 /** 1126 /**
322 * @return {boolean} 1127 * @return {boolean}
323 */ 1128 */
324 isEmpty: function() 1129 isEmpty: function()
325 { 1130 {
326 return this.minimumRecordTime() === 0 && this.maximumRecordTime() === 0; 1131 return this.minimumRecordTime() === 0 && this.maximumRecordTime() === 0;
327 }, 1132 },
328 1133
(...skipping 14 matching lines...) Expand all
343 }, 1148 },
344 1149
345 /** 1150 /**
346 * @return {!Array.<!WebInspector.TimelineModel.Record>} 1151 * @return {!Array.<!WebInspector.TimelineModel.Record>}
347 */ 1152 */
348 eventDividerRecords: function() 1153 eventDividerRecords: function()
349 { 1154 {
350 return this._eventDividerRecords; 1155 return this._eventDividerRecords;
351 }, 1156 },
352 1157
1158
353 __proto__: WebInspector.Object.prototype 1159 __proto__: WebInspector.Object.prototype
354 } 1160 }
355 1161
356 /** 1162 /**
357 * @interface
358 */
359 WebInspector.TimelineModel.Record = function()
360 {
361 }
362
363 WebInspector.TimelineModel.Record.prototype = {
364 /**
365 * @return {?Array.<!ConsoleAgent.CallFrame>}
366 */
367 callSiteStackTrace: function() { },
368
369 /**
370 * @return {?WebInspector.TimelineModel.Record}
371 */
372 initiator: function() { },
373
374 /**
375 * @return {?WebInspector.Target}
376 */
377 target: function() { },
378
379 /**
380 * @return {number}
381 */
382 selfTime: function() { },
383
384 /**
385 * @return {!Array.<!WebInspector.TimelineModel.Record>}
386 */
387 children: function() { },
388
389 /**
390 * @return {number}
391 */
392 startTime: function() { },
393
394 /**
395 * @return {string}
396 */
397 thread: function() { },
398
399 /**
400 * @return {number}
401 */
402 endTime: function() { },
403
404 /**
405 * @param {number} endTime
406 */
407 setEndTime: function(endTime) { },
408
409 /**
410 * @return {!Object}
411 */
412 data: function() { },
413
414 /**
415 * @return {string}
416 */
417 type: function() { },
418
419 /**
420 * @return {string}
421 */
422 frameId: function() { },
423
424 /**
425 * @return {?Array.<!ConsoleAgent.CallFrame>}
426 */
427 stackTrace: function() { },
428
429 /**
430 * @param {string} key
431 * @return {?Object}
432 */
433 getUserObject: function(key) { },
434
435 /**
436 * @param {string} key
437 * @param {?Object|undefined} value
438 */
439 setUserObject: function(key, value) { },
440
441 /**
442 * @return {?Array.<string>}
443 */
444 warnings: function() { }
445 }
446
447 /**
448 * @constructor 1163 * @constructor
449 */ 1164 */
450 WebInspector.TimelineModel.Filter = function() 1165 WebInspector.TimelineModel.Filter = function()
451 { 1166 {
452 /** @type {!WebInspector.TimelineModel} */ 1167 /** @type {!WebInspector.TimelineModel} */
453 this._model; 1168 this._model;
454 } 1169 }
455 1170
456 WebInspector.TimelineModel.Filter.prototype = { 1171 WebInspector.TimelineModel.Filter.prototype = {
457 /** 1172 /**
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 case FileError.NOT_READABLE_ERR: 1325 case FileError.NOT_READABLE_ERR:
611 WebInspector.console.error(WebInspector.UIString("File \"%s\" is not readable", reader.fileName())); 1326 WebInspector.console.error(WebInspector.UIString("File \"%s\" is not readable", reader.fileName()));
612 break; 1327 break;
613 case FileError.ABORT_ERR: 1328 case FileError.ABORT_ERR:
614 break; 1329 break;
615 default: 1330 default:
616 WebInspector.console.error(WebInspector.UIString("An error occurred while reading the file \"%s\"", reader.fileName())); 1331 WebInspector.console.error(WebInspector.UIString("An error occurred while reading the file \"%s\"", reader.fileName()));
617 } 1332 }
618 } 1333 }
619 } 1334 }
1335
1336
1337 /**
1338 * @interface
1339 */
1340 WebInspector.TraceEventFilter = function() { }
1341
1342 WebInspector.TraceEventFilter.prototype = {
1343 /**
1344 * @param {!WebInspector.TracingModel.Event} event
1345 * @return {boolean}
1346 */
1347 accept: function(event) { }
1348 }
1349
1350 /**
1351 * @constructor
1352 * @implements {WebInspector.TraceEventFilter}
1353 * @param {!Array.<string>} eventNames
1354 */
1355 WebInspector.TraceEventNameFilter = function(eventNames)
1356 {
1357 this._eventNames = eventNames.keySet();
1358 }
1359
1360 WebInspector.TraceEventNameFilter.prototype = {
1361 /**
1362 * @param {!WebInspector.TracingModel.Event} event
1363 * @return {boolean}
1364 */
1365 accept: function(event)
1366 {
1367 throw new Error("Not implemented.");
1368 }
1369 }
1370
1371 /**
1372 * @constructor
1373 * @extends {WebInspector.TraceEventNameFilter}
1374 * @param {!Array.<string>} includeNames
1375 */
1376 WebInspector.InclusiveTraceEventNameFilter = function(includeNames)
1377 {
1378 WebInspector.TraceEventNameFilter.call(this, includeNames)
1379 }
1380
1381 WebInspector.InclusiveTraceEventNameFilter.prototype = {
1382 /**
1383 * @override
1384 * @param {!WebInspector.TracingModel.Event} event
1385 * @return {boolean}
1386 */
1387 accept: function(event)
1388 {
1389 return event.category === WebInspector.TracingModel.ConsoleEventCategory || !!this._eventNames[event.name];
1390 },
1391 __proto__: WebInspector.TraceEventNameFilter.prototype
1392 }
1393
1394 /**
1395 * @constructor
1396 * @extends {WebInspector.TraceEventNameFilter}
1397 * @param {!Array.<string>} excludeNames
1398 */
1399 WebInspector.ExclusiveTraceEventNameFilter = function(excludeNames)
1400 {
1401 WebInspector.TraceEventNameFilter.call(this, excludeNames)
1402 }
1403
1404 WebInspector.ExclusiveTraceEventNameFilter.prototype = {
1405 /**
1406 * @override
1407 * @param {!WebInspector.TracingModel.Event} event
1408 * @return {boolean}
1409 */
1410 accept: function(event)
1411 {
1412 return !this._eventNames[event.name];
1413 },
1414 __proto__: WebInspector.TraceEventNameFilter.prototype
1415 }
1416
1417 /**
1418 * @constructor
1419 * @implements {WebInspector.OutputStream}
1420 * @param {!WebInspector.TimelineModel} model
1421 * @param {!{cancel: function()}} reader
1422 * @param {!WebInspector.Progress} progress
1423 */
1424 WebInspector.TracingModelLoader = function(model, reader, progress)
1425 {
1426 this._model = model;
1427 this._reader = reader;
1428 this._progress = progress;
1429 this._buffer = "";
1430 this._firstChunk = true;
1431 this._loader = new WebInspector.TracingModel.Loader(model._tracingModel);
1432 }
1433
1434 WebInspector.TracingModelLoader.prototype = {
1435 /**
1436 * @param {string} chunk
1437 */
1438 write: function(chunk)
1439 {
1440 var data = this._buffer + chunk;
1441 var lastIndex = 0;
1442 var index;
1443 do {
1444 index = lastIndex;
1445 lastIndex = WebInspector.TextUtils.findBalancedCurlyBrackets(data, i ndex);
1446 } while (lastIndex !== -1)
1447
1448 var json = data.slice(0, index) + "]";
1449 this._buffer = data.slice(index);
1450
1451 if (!index)
1452 return;
1453
1454 if (this._firstChunk) {
1455 this._model._startCollectingTraceEvents(true);
1456 } else {
1457 var commaIndex = json.indexOf(",");
1458 if (commaIndex !== -1)
1459 json = json.slice(commaIndex + 1);
1460 json = "[" + json;
1461 }
1462
1463 var items;
1464 try {
1465 items = /** @type {!Array.<!WebInspector.TracingManager.EventPayload >} */ (JSON.parse(json));
1466 } catch (e) {
1467 this._reportErrorAndCancelLoading("Malformed timeline data: " + e);
1468 return;
1469 }
1470
1471 if (this._firstChunk) {
1472 this._firstChunk = false;
1473 if (this._looksLikeAppVersion(items[0])) {
1474 this._reportErrorAndCancelLoading("Old Timeline format is not su pported.");
1475 return;
1476 }
1477 }
1478
1479 try {
1480 this._loader.loadNextChunk(items);
1481 } catch(e) {
1482 this._reportErrorAndCancelLoading("Malformed timeline data: " + e);
1483 return;
1484 }
1485 },
1486
1487 _reportErrorAndCancelLoading: function(messsage)
1488 {
1489 WebInspector.console.error(messsage);
1490 this._model._onTracingComplete();
1491 this._model.reset();
1492 this._reader.cancel();
1493 this._progress.done();
1494 },
1495
1496 _looksLikeAppVersion: function(item)
1497 {
1498 return typeof item === "string" && item.indexOf("Chrome") !== -1;
1499 },
1500
1501 close: function()
1502 {
1503 this._loader.finish();
1504 this._model._onTracingComplete();
1505 }
1506 }
1507
1508 /**
1509 * @constructor
1510 * @param {!WebInspector.OutputStream} stream
1511 * @implements {WebInspector.OutputStreamDelegate}
1512 */
1513 WebInspector.TracingTimelineSaver = function(stream)
1514 {
1515 this._stream = stream;
1516 }
1517
1518 WebInspector.TracingTimelineSaver.prototype = {
1519 onTransferStarted: function()
1520 {
1521 this._stream.write("[");
1522 },
1523
1524 onTransferFinished: function()
1525 {
1526 this._stream.write("]");
1527 },
1528
1529 /**
1530 * @param {!WebInspector.ChunkedReader} reader
1531 */
1532 onChunkTransferred: function(reader) { },
1533
1534 /**
1535 * @param {!WebInspector.ChunkedReader} reader
1536 * @param {!Event} event
1537 */
1538 onError: function(reader, event) { },
1539 }
1540
1541 /**
1542 * @constructor
1543 * @param {!WebInspector.TracingModel.Event} event
1544 */
1545 WebInspector.InvalidationTrackingEvent = function(event)
1546 {
1547 this.type = event.name;
1548 this.frameId = event.args["data"]["frame"];
1549 this.nodeId = event.args["data"]["nodeId"];
1550 this.nodeName = event.args["data"]["nodeName"];
1551 this.paintId = event.args["data"]["paintId"];
1552 this.reason = event.args["data"]["reason"];
1553 this.stackTrace = event.args["data"]["stackTrace"];
1554 }
1555
1556 /**
1557 * @constructor
1558 */
1559 WebInspector.InvalidationTracker = function()
1560 {
1561 this._initializePerFrameState();
1562 }
1563
1564 WebInspector.InvalidationTracker.prototype = {
1565 /**
1566 * @param {!WebInspector.TracingModel.Event} event
1567 */
1568 addInvalidation: function(event)
1569 {
1570 var invalidation = new WebInspector.InvalidationTrackingEvent(event);
1571
1572 this._startNewFrameIfNeeded();
1573 if (!invalidation.nodeId && !invalidation.paintId) {
1574 console.error("Invalidation lacks node information.");
1575 console.error(invalidation);
1576 }
1577
1578 // Record the paintIds for style recalc or layout invalidations.
1579 // FIXME: This O(n^2) loop could be optimized with a map.
1580 var recordTypes = WebInspector.TimelineModel.RecordType;
1581 if (invalidation.type == recordTypes.PaintInvalidationTracking)
1582 this._invalidationEvents.forEach(updatePaintId);
1583 else
1584 this._invalidationEvents.push(invalidation);
1585
1586 function updatePaintId(invalidationToUpdate)
1587 {
1588 if (invalidationToUpdate.nodeId !== invalidation.nodeId)
1589 return;
1590 if (invalidationToUpdate.type === recordTypes.StyleRecalcInvalidatio nTracking
1591 || invalidationToUpdate.type === recordTypes.LayoutInvalidat ionTracking) {
1592 invalidationToUpdate.paintId = invalidation.paintId;
1593 }
1594 }
1595 },
1596
1597 /**
1598 * @param {!WebInspector.TracingModel.Event} styleRecalcEvent
1599 */
1600 didRecalcStyle: function(styleRecalcEvent)
1601 {
1602 var recalcFrameId = styleRecalcEvent.args["frame"];
1603 var index = this._lastStyleRecalcEventIndex;
1604 var invalidationCount = this._invalidationEvents.length;
1605 for (; index < invalidationCount; index++) {
1606 var invalidation = this._invalidationEvents[index];
1607 if (invalidation.type !== WebInspector.TimelineModel.RecordType.Styl eRecalcInvalidationTracking)
1608 continue;
1609 if (invalidation.frameId === recalcFrameId)
1610 this._addInvalidationTrackingEvent(styleRecalcEvent, invalidatio n);
1611 }
1612
1613 this._lastStyleRecalcEventIndex = invalidationCount;
1614 },
1615
1616 /**
1617 * @param {!WebInspector.TracingModel.Event} layoutEvent
1618 */
1619 didLayout: function(layoutEvent)
1620 {
1621 var layoutFrameId = layoutEvent.args["beginData"]["frame"];
1622 var index = this._lastLayoutEventIndex;
1623 var invalidationCount = this._invalidationEvents.length;
1624 for (; index < invalidationCount; index++) {
1625 var invalidation = this._invalidationEvents[index];
1626 if (invalidation.type !== WebInspector.TimelineModel.RecordType.Layo utInvalidationTracking)
1627 continue;
1628 if (invalidation.frameId === layoutFrameId)
1629 this._addInvalidationTrackingEvent(layoutEvent, invalidation);
1630 }
1631
1632 this._lastLayoutEventIndex = invalidationCount;
1633 },
1634
1635 /**
1636 * @param {!WebInspector.TracingModel.Event} paintEvent
1637 */
1638 didPaint: function(paintEvent)
1639 {
1640 this._didPaint = true;
1641
1642 // If a paint doesn't have a corresponding graphics layer id, it paints
1643 // into its parent so add an effectivePaintId to these events.
1644 var layerId = paintEvent.args["data"]["layerId"];
1645 if (layerId)
1646 this._lastPaintWithLayer = paintEvent;
1647 if (!this._lastPaintWithLayer) {
1648 console.error("Failed to find the paint container for a paint event. ");
1649 return;
1650 }
1651
1652 var effectivePaintId = this._lastPaintWithLayer.args["data"]["nodeId"];
1653 var frameId = paintEvent.args["data"]["frame"];
1654 this._invalidationEvents.forEach(recordInvalidationForPaint.bind(this));
1655
1656 /**
1657 * @param {!WebInspector.InvalidationTrackingEvent} invalidation
1658 * @this {WebInspector.InvalidationTracker}
1659 */
1660 function recordInvalidationForPaint(invalidation)
1661 {
1662 if (invalidation.paintId === effectivePaintId && invalidation.frameI d === frameId)
1663 this._addInvalidationTrackingEvent(paintEvent, invalidation);
1664 }
1665 },
1666
1667 /**
1668 * @param {!WebInspector.TracingModel.Event} event
1669 * @param {!WebInspector.InvalidationTrackingEvent} invalidation
1670 */
1671 _addInvalidationTrackingEvent: function(event, invalidation)
1672 {
1673 if (!event.invalidationTrackingEvents)
1674 event.invalidationTrackingEvents = [ invalidation ];
1675 else
1676 event.invalidationTrackingEvents.push(invalidation);
1677 },
1678
1679 _startNewFrameIfNeeded: function()
1680 {
1681 if (!this._didPaint)
1682 return;
1683
1684 this._initializePerFrameState();
1685 },
1686
1687 _initializePerFrameState: function()
1688 {
1689 /** @type {!Array.<!WebInspector.InvalidationTrackingEvent>} */
1690 this._invalidationEvents = [];
1691 this._lastStyleRecalcEventIndex = 0;
1692 this._lastLayoutEventIndex = 0;
1693 this._lastPaintWithLayer = undefined;
1694 this._didPaint = false;
1695 }
1696 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/timeline/TimelineJSProfile.js ('k') | Source/devtools/front_end/timeline/TimelinePanel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698