OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @param {!WebInspector.TracingModel} tracingModel | 6 * @param {!WebInspector.TracingModel} tracingModel |
7 * @constructor | 7 * @constructor |
8 * @extends {WebInspector.TargetAwareObject} | 8 * @extends {WebInspector.TimelineModel} |
9 */ | 9 */ |
10 WebInspector.TracingTimelineModel = function(tracingModel) | 10 WebInspector.TracingTimelineModel = function(tracingModel) |
11 { | 11 { |
12 WebInspector.TargetAwareObject.call(this, tracingModel.target()); | 12 WebInspector.TimelineModel.call(this, tracingModel.target()); |
13 this._tracingModel = tracingModel; | 13 this._tracingModel = tracingModel; |
14 this._mainThreadEvents = []; | 14 this._mainThreadEvents = []; |
15 this._inspectedTargetEvents = []; | 15 this._inspectedTargetEvents = []; |
16 | |
17 this.reset(); | |
16 } | 18 } |
17 | 19 |
18 WebInspector.TracingTimelineModel.RecordType = { | 20 WebInspector.TracingTimelineModel.RecordType = { |
19 Program: "Program", | 21 Program: "Program", |
20 EventDispatch: "EventDispatch", | 22 EventDispatch: "EventDispatch", |
21 | 23 |
22 GPUTask: "GPUTask", | 24 GPUTask: "GPUTask", |
23 | 25 |
24 RequestMainThreadFrame: "RequestMainThreadFrame", | 26 RequestMainThreadFrame: "RequestMainThreadFrame", |
25 BeginFrame: "BeginFrame", | 27 BeginFrame: "BeginFrame", |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 { | 107 { |
106 var categories; | 108 var categories; |
107 if (WebInspector.experimentsSettings.timelineTracingMode.isEnabled()) { | 109 if (WebInspector.experimentsSettings.timelineTracingMode.isEnabled()) { |
108 categories = WebInspector.TracingTimelineModel.defaultTracingCategor yFilter; | 110 categories = WebInspector.TracingTimelineModel.defaultTracingCategor yFilter; |
109 } else { | 111 } else { |
110 var categoriesArray = ["disabled-by-default-devtools.timeline", "dev tools"]; | 112 var categoriesArray = ["disabled-by-default-devtools.timeline", "dev tools"]; |
111 if (captureStacks) | 113 if (captureStacks) |
112 categoriesArray.push("disabled-by-default-devtools.timeline.stac k"); | 114 categoriesArray.push("disabled-by-default-devtools.timeline.stac k"); |
113 categories = categoriesArray.join(","); | 115 categories = categoriesArray.join(","); |
114 } | 116 } |
115 this._tracingModel.start(categories, ""); | 117 this._startRecordingWithCategories(categories); |
116 this.willStartRecordingTraceEvents(); | |
117 }, | 118 }, |
118 | 119 |
119 stopRecording: function() | 120 stopRecording: function() |
120 { | 121 { |
121 this._tracingModel.stop(this.didStopRecordingTraceEvents.bind(this)); | 122 this._tracingModel.stop(this._didStopRecordingTraceEvents.bind(this)); |
122 }, | 123 }, |
123 | 124 |
124 willStartRecordingTraceEvents: function() | 125 /** |
126 * @param {string} sessionId | |
127 * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events | |
128 */ | |
129 setEventsForTest: function(sessionId, events) | |
125 { | 130 { |
126 this._mainThreadEvents = []; | 131 this._didStartRecordingTraceEvents(); |
127 this._inspectedTargetEvents = []; | 132 this._tracingModel.setEventsForTest(sessionId, events); |
133 this._didStopRecordingTraceEvents(); | |
128 }, | 134 }, |
129 | 135 |
130 didStopRecordingTraceEvents: function() | 136 /** |
137 * @param {string} categories | |
138 */ | |
139 _startRecordingWithCategories: function(categories) | |
140 { | |
141 this._tracingModel.start(categories, "", this._didStartRecordingTraceEve nts.bind(this)); | |
142 }, | |
143 | |
144 _didStartRecordingTraceEvents: function() | |
145 { | |
146 this.reset(); | |
147 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStarted); | |
148 }, | |
149 | |
150 _didStopRecordingTraceEvents: function() | |
131 { | 151 { |
132 var events = this._tracingModel.devtoolsMetadataEvents(); | 152 var events = this._tracingModel.devtoolsMetadataEvents(); |
133 events.sort(WebInspector.TracingModel.Event.compareStartTime); | 153 events.sort(WebInspector.TracingModel.Event.compareStartTime); |
134 | 154 |
135 this._resetProcessingState(); | 155 this._resetProcessingState(); |
136 for (var i = 0, length = events.length; i < length; i++) { | 156 for (var i = 0, length = events.length; i < length; i++) { |
137 var event = events[i]; | 157 var event = events[i]; |
138 var process = event.thread.process(); | 158 var process = event.thread.process(); |
139 var startTime = event.startTime; | 159 var startTime = event.startTime; |
140 | 160 |
141 var endTime = Infinity; | 161 var endTime = Infinity; |
142 if (i + 1 < length) | 162 if (i + 1 < length) |
143 endTime = events[i + 1].startTime; | 163 endTime = events[i + 1].startTime; |
144 | 164 |
145 process.sortedThreads().forEach(this._processThreadEvents.bind(this, startTime, endTime, event.thread)); | 165 process.sortedThreads().forEach(this._processThreadEvents.bind(this, startTime, endTime, event.thread)); |
146 } | 166 } |
147 this._resetProcessingState(); | 167 this._resetProcessingState(); |
148 | 168 |
149 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare StartTime); | 169 this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compare StartTime); |
150 | 170 |
171 this._buildTimelineRecords(); | |
151 this.dispatchEventToListeners(WebInspector.TracingTimelineModel.Events.T racingComplete); | 172 this.dispatchEventToListeners(WebInspector.TracingTimelineModel.Events.T racingComplete); |
173 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped); | |
caseq
2014/06/09 11:59:03
do we really need two events for this?
yurys
2014/06/09 12:16:13
No. I will address this in a separate patch.
| |
152 }, | 174 }, |
153 | 175 |
154 /** | 176 /** |
155 * @return {?number} | 177 * @return {?number} |
156 */ | 178 */ |
157 minimumRecordTime: function() | 179 minimumRecordTime: function() |
158 { | 180 { |
159 return this._tracingModel.minimumRecordTime(); | 181 return this._tracingModel.minimumRecordTime(); |
160 }, | 182 }, |
161 | 183 |
(...skipping 14 matching lines...) Expand all Loading... | |
176 }, | 198 }, |
177 | 199 |
178 /** | 200 /** |
179 * @return {!Array.<!WebInspector.TracingModel.Event>} | 201 * @return {!Array.<!WebInspector.TracingModel.Event>} |
180 */ | 202 */ |
181 mainThreadEvents: function() | 203 mainThreadEvents: function() |
182 { | 204 { |
183 return this._mainThreadEvents; | 205 return this._mainThreadEvents; |
184 }, | 206 }, |
185 | 207 |
208 reset: function() | |
209 { | |
210 this._mainThreadEvents = []; | |
211 this._inspectedTargetEvents = []; | |
212 WebInspector.TimelineModel.prototype.reset.call(this); | |
213 }, | |
214 | |
215 _buildTimelineRecords: function() | |
216 { | |
217 var recordStack = []; | |
218 var mainThreadEvents = this._mainThreadEvents; | |
219 for (var i = 0, size = mainThreadEvents.length; i < size; ++i) { | |
220 var event = mainThreadEvents[i]; | |
221 while (recordStack.length) { | |
222 var top = recordStack.peekLast(); | |
223 if (top._event.endTime >= event.startTime) | |
224 break; | |
225 recordStack.pop(); | |
226 } | |
227 var parentRecord = recordStack.peekLast() || null; | |
228 var record = new WebInspector.TracingTimelineModel.TraceEventRecord( this, event, parentRecord); | |
229 if (WebInspector.TimelineUIUtils.isEventDivider(record)) | |
230 this._eventDividerRecords.push(record); | |
231 if (!recordStack.length) | |
232 this._addTopLevelRecord(record); | |
233 if (event.endTime) | |
234 recordStack.push(record); | |
235 } | |
236 }, | |
237 | |
238 /** | |
239 * @param {!WebInspector.TracingTimelineModel.TraceEventRecord} record | |
240 */ | |
241 _addTopLevelRecord: function(record) | |
242 { | |
243 this._updateBoundaries(record); | |
244 this._records.push(record); | |
245 if (record.type() === WebInspector.TimelineModel.RecordType.Program) | |
246 this._mainThreadTasks.push(record); | |
247 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask) | |
248 this._gpuThreadTasks.push(record); | |
249 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd ded, record); | |
250 }, | |
251 | |
186 _resetProcessingState: function() | 252 _resetProcessingState: function() |
187 { | 253 { |
188 this._sendRequestEvents = {}; | 254 this._sendRequestEvents = {}; |
189 this._timerEvents = {}; | 255 this._timerEvents = {}; |
190 this._requestAnimationFrameEvents = {}; | 256 this._requestAnimationFrameEvents = {}; |
191 this._layoutInvalidate = {}; | 257 this._layoutInvalidate = {}; |
192 this._lastScheduleStyleRecalculation = {}; | 258 this._lastScheduleStyleRecalculation = {}; |
193 this._webSocketCreateEvents = {}; | 259 this._webSocketCreateEvents = {}; |
194 this._paintImageEventByPixelRefId = {}; | 260 this._paintImageEventByPixelRefId = {}; |
195 | 261 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 _findAncestorEvent: function(name) | 436 _findAncestorEvent: function(name) |
371 { | 437 { |
372 for (var i = this._eventStack.length - 1; i >= 0; --i) { | 438 for (var i = this._eventStack.length - 1; i >= 0; --i) { |
373 var event = this._eventStack[i]; | 439 var event = this._eventStack[i]; |
374 if (event.name === name) | 440 if (event.name === name) |
375 return event; | 441 return event; |
376 } | 442 } |
377 return null; | 443 return null; |
378 }, | 444 }, |
379 | 445 |
380 __proto__: WebInspector.TargetAwareObject.prototype | 446 __proto__: WebInspector.TimelineModel.prototype |
381 } | 447 } |
448 | |
449 /** | |
450 * @constructor | |
451 * @implements {WebInspector.TimelineModel.Record} | |
452 * @param {!WebInspector.TimelineModel} model | |
453 * @param {!WebInspector.TracingModel.Event} traceEvent | |
454 * @param {?WebInspector.TracingTimelineModel.TraceEventRecord} parentRecord | |
455 */ | |
456 WebInspector.TracingTimelineModel.TraceEventRecord = function(model, traceEvent, parentRecord) | |
457 { | |
458 this._model = model; | |
459 this._event = traceEvent; | |
460 traceEvent._timelineRecord = this; | |
461 if (parentRecord) { | |
462 this.parent = parentRecord; | |
463 parentRecord._children.push(this); | |
464 } | |
465 this._children = []; | |
466 } | |
467 | |
468 WebInspector.TracingTimelineModel.TraceEventRecord.prototype = { | |
469 /** | |
470 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
471 */ | |
472 callSiteStackTrace: function() | |
473 { | |
474 var initiator = this._event.initiator; | |
475 return initiator ? initiator.stackTrace : null; | |
476 }, | |
477 | |
478 /** | |
479 * @return {?WebInspector.TimelineModel.Record} | |
480 */ | |
481 initiator: function() | |
482 { | |
483 var initiator = this._event.initiator; | |
484 return initiator ? initiator._timelineRecord : null; | |
485 }, | |
486 | |
487 /** | |
488 * @return {!WebInspector.Target} | |
489 */ | |
490 target: function() | |
491 { | |
492 return this._model.target(); | |
493 }, | |
494 | |
495 /** | |
496 * @return {number} | |
497 */ | |
498 selfTime: function() | |
499 { | |
500 return this._event.selfTime; | |
501 }, | |
502 | |
503 /** | |
504 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
505 */ | |
506 children: function() | |
507 { | |
508 return this._children; | |
509 }, | |
510 | |
511 /** | |
512 * @return {!WebInspector.TimelineCategory} | |
513 */ | |
514 category: function() | |
515 { | |
516 var style = WebInspector.TimelineUIUtils.styleForTimelineEvent(this._eve nt.name); | |
517 return style.category; | |
518 }, | |
519 | |
520 /** | |
521 * @return {string} | |
522 */ | |
523 title: function() | |
524 { | |
525 return WebInspector.TimelineUIUtils.recordTitle(this, this._model); | |
526 }, | |
527 | |
528 /** | |
529 * @return {number} | |
530 */ | |
531 startTime: function() | |
532 { | |
533 return this._event.startTime; | |
534 }, | |
535 | |
536 /** | |
537 * @return {string|undefined} | |
538 */ | |
539 thread: function() | |
540 { | |
541 return "CPU"; | |
542 }, | |
543 | |
544 /** | |
545 * @return {number} | |
546 */ | |
547 endTime: function() | |
548 { | |
549 return this._event.endTime || this._event.startTime; | |
550 }, | |
551 | |
552 /** | |
553 * @param {number} endTime | |
554 */ | |
555 setEndTime: function(endTime) | |
556 { | |
557 throw new Error("Unsupported operation setEndTime"); | |
558 }, | |
559 | |
560 /** | |
561 * @return {!Object} | |
562 */ | |
563 data: function() | |
564 { | |
565 return this._event.args.data; | |
566 }, | |
567 | |
568 /** | |
569 * @return {string} | |
570 */ | |
571 type: function() | |
572 { | |
573 return this._event.name; | |
574 }, | |
575 | |
576 /** | |
577 * @return {string} | |
578 */ | |
579 frameId: function() | |
580 { | |
581 switch (this._event.name) { | |
582 case WebInspector.TracingTimelineModel.RecordType.ScheduleStyleRecalcula tion: | |
583 case WebInspector.TracingTimelineModel.RecordType.RecalculateStyles: | |
584 case WebInspector.TracingTimelineModel.RecordType.InvalidateLayout: | |
585 return this._event.args["frameId"]; | |
586 case WebInspector.TracingTimelineModel.RecordType.Layout: | |
587 return this._event.args["beginData"]["frameId"]; | |
588 default: | |
589 var data = this._event.args.data; | |
590 return (data && data["frame"]) || ""; | |
591 } | |
592 }, | |
593 | |
594 /** | |
595 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
596 */ | |
597 stackTrace: function() | |
598 { | |
599 return this._event.stackTrace; | |
600 }, | |
601 | |
602 /** | |
603 * @param {string} key | |
604 * @return {?Object} | |
605 */ | |
606 getUserObject: function(key) | |
607 { | |
608 if (key === "TimelineUIUtils::preview-element") | |
609 return this._event.previewElement; | |
610 throw new Error("Unexpected key: " + key); | |
611 }, | |
612 | |
613 /** | |
614 * @param {string} key | |
615 * @param {?Object|undefined} value | |
616 */ | |
617 setUserObject: function(key, value) | |
618 { | |
619 if (key !== "TimelineUIUtils::preview-element") | |
620 throw new Error("Unexpected key: " + key); | |
621 this._event.previewElement = /** @type {?Element} */ (value); | |
622 }, | |
623 | |
624 /** | |
625 * @return {!Object.<string, number>} | |
626 */ | |
627 aggregatedStats: function() | |
628 { | |
629 return {}; | |
630 }, | |
631 | |
632 /** | |
633 * @return {?Array.<string>} | |
634 */ | |
635 warnings: function() | |
636 { | |
637 if (this._event.warning) | |
638 return [this._event.warning]; | |
639 return null; | |
640 }, | |
641 | |
642 /** | |
643 * @param {!RegExp} regExp | |
644 * @return {boolean} | |
645 */ | |
646 testContentMatching: function(regExp) | |
647 { | |
648 var tokens = [this.title()]; | |
649 var data = this._event.args.data; | |
650 if (data) { | |
651 for (var key in data) | |
652 tokens.push(data[key]); | |
653 } | |
654 return regExp.test(tokens.join("|")); | |
655 } | |
656 } | |
OLD | NEW |