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 * @constructor | 6 * @constructor |
7 * @param {!WebInspector.TracingModel} tracingModel | 7 * @param {!WebInspector.TracingModel} tracingModel |
8 * @param {!WebInspector.TimelineModel.Filter} recordFilter | 8 * @param {!WebInspector.TimelineModel.Filter} recordFilter |
9 * @extends {WebInspector.TimelineModel} | 9 * @extends {WebInspector.TimelineModel} |
10 */ | 10 */ |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 GPUTask: "GPUTask", | 25 GPUTask: "GPUTask", |
26 | 26 |
27 RequestMainThreadFrame: "RequestMainThreadFrame", | 27 RequestMainThreadFrame: "RequestMainThreadFrame", |
28 BeginFrame: "BeginFrame", | 28 BeginFrame: "BeginFrame", |
29 BeginMainThreadFrame: "BeginMainThreadFrame", | 29 BeginMainThreadFrame: "BeginMainThreadFrame", |
30 ActivateLayerTree: "ActivateLayerTree", | 30 ActivateLayerTree: "ActivateLayerTree", |
31 DrawFrame: "DrawFrame", | 31 DrawFrame: "DrawFrame", |
32 ScheduleStyleRecalculation: "ScheduleStyleRecalculation", | 32 ScheduleStyleRecalculation: "ScheduleStyleRecalculation", |
33 RecalculateStyles: "RecalculateStyles", | 33 RecalculateStyles: "RecalculateStyles", |
| 34 StyleInvalidationTracking: "StyleInvalidationTracking", |
| 35 LayoutInvalidationTracking: "LayoutInvalidationTracking", |
| 36 PaintInvalidationTracking: "PaintInvalidationTracking", |
34 InvalidateLayout: "InvalidateLayout", | 37 InvalidateLayout: "InvalidateLayout", |
35 Layout: "Layout", | 38 Layout: "Layout", |
36 UpdateLayer: "UpdateLayer", | 39 UpdateLayer: "UpdateLayer", |
37 UpdateLayerTree: "UpdateLayerTree", | 40 UpdateLayerTree: "UpdateLayerTree", |
38 PaintSetup: "PaintSetup", | 41 PaintSetup: "PaintSetup", |
39 Paint: "Paint", | 42 Paint: "Paint", |
40 PaintImage: "PaintImage", | 43 PaintImage: "PaintImage", |
41 Rasterize: "Rasterize", | 44 Rasterize: "Rasterize", |
42 RasterTask: "RasterTask", | 45 RasterTask: "RasterTask", |
43 ScrollLayer: "ScrollLayer", | 46 ScrollLayer: "ScrollLayer", |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 this.events = []; | 112 this.events = []; |
110 /** @type {!Array.<!Array.<!WebInspector.TracingModel.Event>>} */ | 113 /** @type {!Array.<!Array.<!WebInspector.TracingModel.Event>>} */ |
111 this.asyncEvents = []; | 114 this.asyncEvents = []; |
112 } | 115 } |
113 | 116 |
114 WebInspector.TracingTimelineModel.prototype = { | 117 WebInspector.TracingTimelineModel.prototype = { |
115 /** | 118 /** |
116 * @param {boolean} captureStacks | 119 * @param {boolean} captureStacks |
117 * @param {boolean} captureMemory | 120 * @param {boolean} captureMemory |
118 * @param {boolean} capturePictures | 121 * @param {boolean} capturePictures |
| 122 * @param {boolean} captureInvalidationTracking |
119 */ | 123 */ |
120 startRecording: function(captureStacks, captureMemory, capturePictures) | 124 startRecording: function(captureStacks, captureMemory, capturePictures, capt
ureInvalidationTracking) |
121 { | 125 { |
122 function disabledByDefault(category) | 126 function disabledByDefault(category) |
123 { | 127 { |
124 return "disabled-by-default-" + category; | 128 return "disabled-by-default-" + category; |
125 } | 129 } |
126 var categoriesArray = [ | 130 var categoriesArray = [ |
127 "-*", | 131 "-*", |
128 disabledByDefault("devtools.timeline"), | 132 disabledByDefault("devtools.timeline"), |
129 disabledByDefault("devtools.timeline.frame"), | 133 disabledByDefault("devtools.timeline.frame"), |
130 WebInspector.TracingModel.ConsoleEventCategory | 134 WebInspector.TracingModel.ConsoleEventCategory |
131 ]; | 135 ]; |
132 if (captureStacks) { | 136 if (captureStacks) { |
133 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); | 137 categoriesArray.push(disabledByDefault("devtools.timeline.stack")); |
134 if (WebInspector.experimentsSettings.timelineJSCPUProfile.isEnabled(
)) { | 138 if (WebInspector.experimentsSettings.timelineJSCPUProfile.isEnabled(
)) { |
135 this._jsProfilerStarted = true; | 139 this._jsProfilerStarted = true; |
136 this._currentTarget = WebInspector.context.flavor(WebInspector.T
arget); | 140 this._currentTarget = WebInspector.context.flavor(WebInspector.T
arget); |
137 this._configureCpuProfilerSamplingInterval(); | 141 this._configureCpuProfilerSamplingInterval(); |
138 this._currentTarget.profilerAgent().start(); | 142 this._currentTarget.profilerAgent().start(); |
139 } | 143 } |
140 } | 144 } |
141 if (capturePictures) { | 145 if (capturePictures) { |
142 categoriesArray = categoriesArray.concat([ | 146 categoriesArray = categoriesArray.concat([ |
143 disabledByDefault("devtools.timeline.layers"), | 147 disabledByDefault("devtools.timeline.layers"), |
144 disabledByDefault("devtools.timeline.picture"), | 148 disabledByDefault("devtools.timeline.picture"), |
145 disabledByDefault("blink.graphics_context_annotations")]); | 149 disabledByDefault("blink.graphics_context_annotations")]); |
146 } | 150 } |
| 151 if (captureInvalidationTracking) { |
| 152 categoriesArray = categoriesArray.concat([ |
| 153 disabledByDefault("devtools.timeline.invalidationTracking")]); |
| 154 } |
147 var categories = categoriesArray.join(","); | 155 var categories = categoriesArray.join(","); |
148 this._startRecordingWithCategories(categories); | 156 this._startRecordingWithCategories(categories); |
149 }, | 157 }, |
150 | 158 |
151 stopRecording: function() | 159 stopRecording: function() |
152 { | 160 { |
153 this._stopCallbackBarrier = new CallbackBarrier(); | 161 this._stopCallbackBarrier = new CallbackBarrier(); |
154 if (this._jsProfilerStarted) { | 162 if (this._jsProfilerStarted) { |
155 this._currentTarget.profilerAgent().stop(this._stopCallbackBarrier.c
reateCallback(this._didStopRecordingJSSamples.bind(this))); | 163 this._currentTarget.profilerAgent().stop(this._stopCallbackBarrier.c
reateCallback(this._didStopRecordingJSSamples.bind(this))); |
156 this._jsProfilerStarted = false; | 164 this._jsProfilerStarted = false; |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 if (record.type() === WebInspector.TracingTimelineModel.RecordType.GPUTa
sk) | 411 if (record.type() === WebInspector.TracingTimelineModel.RecordType.GPUTa
sk) |
404 this._gpuThreadTasks.push(record); | 412 this._gpuThreadTasks.push(record); |
405 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd
ded, record); | 413 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd
ded, record); |
406 }, | 414 }, |
407 | 415 |
408 _resetProcessingState: function() | 416 _resetProcessingState: function() |
409 { | 417 { |
410 this._sendRequestEvents = {}; | 418 this._sendRequestEvents = {}; |
411 this._timerEvents = {}; | 419 this._timerEvents = {}; |
412 this._requestAnimationFrameEvents = {}; | 420 this._requestAnimationFrameEvents = {}; |
| 421 this._invalidationTracker = new WebInspector.InvalidationTracker(); |
413 this._layoutInvalidate = {}; | 422 this._layoutInvalidate = {}; |
414 this._lastScheduleStyleRecalculation = {}; | 423 this._lastScheduleStyleRecalculation = {}; |
415 this._webSocketCreateEvents = {}; | 424 this._webSocketCreateEvents = {}; |
416 this._paintImageEventByPixelRefId = {}; | 425 this._paintImageEventByPixelRefId = {}; |
417 this._lastPaintForLayer = {}; | 426 this._lastPaintForLayer = {}; |
418 this._lastRecalculateStylesEvent = null; | 427 this._lastRecalculateStylesEvent = null; |
419 this._currentScriptEvent = null; | 428 this._currentScriptEvent = null; |
420 this._eventStack = []; | 429 this._eventStack = []; |
421 }, | 430 }, |
422 | 431 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 | 524 |
516 case recordTypes.ScheduleStyleRecalculation: | 525 case recordTypes.ScheduleStyleRecalculation: |
517 this._lastScheduleStyleRecalculation[event.args["frame"]] = event; | 526 this._lastScheduleStyleRecalculation[event.args["frame"]] = event; |
518 break; | 527 break; |
519 | 528 |
520 case recordTypes.RecalculateStyles: | 529 case recordTypes.RecalculateStyles: |
521 event.initiator = this._lastScheduleStyleRecalculation[event.args["f
rame"]]; | 530 event.initiator = this._lastScheduleStyleRecalculation[event.args["f
rame"]]; |
522 this._lastRecalculateStylesEvent = event; | 531 this._lastRecalculateStylesEvent = event; |
523 break; | 532 break; |
524 | 533 |
| 534 case recordTypes.StyleInvalidationTracking: |
| 535 this._invalidationTracker.addStyleInvalidation({ |
| 536 frameId: event.args.data.frame, |
| 537 nodeId: event.args.data.nodeId, |
| 538 nodeName: event.args.data.nodeName, |
| 539 callstack: event.args.data.callstack |
| 540 }); |
| 541 break; |
| 542 |
| 543 case recordTypes.LayoutInvalidationTracking: |
| 544 this._invalidationTracker.addLayoutInvalidation({ |
| 545 frameId: event.args.data.frame, |
| 546 rendererId: event.args.data.rendererId, |
| 547 nodeId: event.args.data.nodeId, |
| 548 nodeName: event.args.data.nodeName, |
| 549 callstack: event.args.data.callstack |
| 550 }); |
| 551 break; |
| 552 |
| 553 case recordTypes.PaintInvalidationTracking: |
| 554 this._invalidationTracker.addPaintInvalidation({ |
| 555 frameId: event.args.data.frame, |
| 556 rendererId: event.args.data.rendererId, |
| 557 nodeId: event.args.data.nodeId, |
| 558 nodeName: event.args.data.nodeName, |
| 559 paintId: event.args.data.paintId |
| 560 }); |
| 561 break; |
| 562 |
525 case recordTypes.InvalidateLayout: | 563 case recordTypes.InvalidateLayout: |
526 // Consider style recalculation as a reason for layout invalidation, | 564 // Consider style recalculation as a reason for layout invalidation, |
527 // but only if we had no earlier layout invalidation records. | 565 // but only if we had no earlier layout invalidation records. |
528 var layoutInitator = event; | 566 var layoutInitator = event; |
529 var frameId = event.args["frame"]; | 567 var frameId = event.args["frame"]; |
530 if (!this._layoutInvalidate[frameId] && this._lastRecalculateStylesE
vent && this._lastRecalculateStylesEvent.endTime > event.startTime) | 568 if (!this._layoutInvalidate[frameId] && this._lastRecalculateStylesE
vent && this._lastRecalculateStylesEvent.endTime > event.startTime) |
531 layoutInitator = this._lastRecalculateStylesEvent.initiator; | 569 layoutInitator = this._lastRecalculateStylesEvent.initiator; |
532 this._layoutInvalidate[frameId] = layoutInitator; | 570 this._layoutInvalidate[frameId] = layoutInitator; |
533 break; | 571 break; |
534 | 572 |
(...skipping 21 matching lines...) Expand all Loading... |
556 case recordTypes.FunctionCall: | 594 case recordTypes.FunctionCall: |
557 if (!this._currentScriptEvent) | 595 if (!this._currentScriptEvent) |
558 this._currentScriptEvent = event; | 596 this._currentScriptEvent = event; |
559 break; | 597 break; |
560 | 598 |
561 case recordTypes.SetLayerTreeId: | 599 case recordTypes.SetLayerTreeId: |
562 this._inspectedTargetLayerTreeId = event.args["layerTreeId"]; | 600 this._inspectedTargetLayerTreeId = event.args["layerTreeId"]; |
563 break; | 601 break; |
564 | 602 |
565 case recordTypes.Paint: | 603 case recordTypes.Paint: |
| 604 this._invalidationTracker.updatePaint(event); |
566 event.highlightQuad = event.args["data"]["clip"]; | 605 event.highlightQuad = event.args["data"]["clip"]; |
567 event.backendNodeId = event.args["data"]["nodeId"]; | 606 event.backendNodeId = event.args["data"]["nodeId"]; |
568 var layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLay
er); | 607 var layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLay
er); |
569 if (!layerUpdateEvent || layerUpdateEvent.args["layerTreeId"] !== th
is._inspectedTargetLayerTreeId) | 608 if (!layerUpdateEvent || layerUpdateEvent.args["layerTreeId"] !== th
is._inspectedTargetLayerTreeId) |
570 break; | 609 break; |
571 // Only keep layer paint events, skip paints for subframes that get
painted to the same layer as parent. | 610 // Only keep layer paint events, skip paints for subframes that get
painted to the same layer as parent. |
572 if (!event.args["data"]["layerId"]) | 611 if (!event.args["data"]["layerId"]) |
573 break; | 612 break; |
574 this._lastPaintForLayer[layerUpdateEvent.args["layerId"]] = event; | 613 this._lastPaintForLayer[layerUpdateEvent.args["layerId"]] = event; |
575 break; | 614 break; |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 }, | 1082 }, |
1044 | 1083 |
1045 _didWriteNextChunk: function(stream) | 1084 _didWriteNextChunk: function(stream) |
1046 { | 1085 { |
1047 if (this._recordIndex === this._payloads.length) | 1086 if (this._recordIndex === this._payloads.length) |
1048 stream.close(); | 1087 stream.close(); |
1049 else | 1088 else |
1050 this._writeNextChunk(stream); | 1089 this._writeNextChunk(stream); |
1051 } | 1090 } |
1052 } | 1091 } |
| 1092 |
| 1093 /** |
| 1094 * TODO: Properly doc this class. |
| 1095 * |
| 1096 * Track style, layout, and paint invalidation events. |
| 1097 */ |
| 1098 WebInspector.InvalidationTracker = function() |
| 1099 { |
| 1100 // Invalidation events for the current frame. |
| 1101 this._styleTrackingEvents = {}; |
| 1102 this._layoutTrackingEvents = {}; |
| 1103 this._paintTrackingEvents = {}; |
| 1104 |
| 1105 // FIXME: This is used to clear out the tracking event maps but it may |
| 1106 // not be sufficient if there are multiple frame ids. |
| 1107 this._lastFrameId = -1; |
| 1108 |
| 1109 this._didPaint = false; |
| 1110 } |
| 1111 |
| 1112 WebInspector.InvalidationTracker.prototype = { |
| 1113 |
| 1114 addStyleInvalidation: function(invalidation) |
| 1115 { |
| 1116 this._startNewFrameIfNeeded(); |
| 1117 |
| 1118 var frameId = invalidation.frameId; |
| 1119 this._lastFrameId = frameId; |
| 1120 |
| 1121 if (!invalidation.nodeId) { |
| 1122 console.error('Style invalidation lacks node information.'); |
| 1123 console.error(invalidation); |
| 1124 } |
| 1125 |
| 1126 if (this._styleTrackingEvents[frameId] === undefined) |
| 1127 this._styleTrackingEvents[frameId] = []; |
| 1128 this._styleTrackingEvents[frameId].push(invalidation); |
| 1129 }, |
| 1130 |
| 1131 addLayoutInvalidation: function(invalidation) |
| 1132 { |
| 1133 this._startNewFrameIfNeeded(); |
| 1134 |
| 1135 var frameId = invalidation.frameId; |
| 1136 this._lastFrameId = frameId; |
| 1137 |
| 1138 if (!invalidation.nodeId && !invalidation.rendererId) { |
| 1139 console.error('Layout invalidation lacks node or renderer informatio
n.'); |
| 1140 console.error(invalidation); |
| 1141 } |
| 1142 |
| 1143 if (this._layoutTrackingEvents[frameId] === undefined) |
| 1144 this._layoutTrackingEvents[frameId] = []; |
| 1145 this._layoutTrackingEvents[frameId].push(invalidation); |
| 1146 }, |
| 1147 |
| 1148 addPaintInvalidation: function(invalidation) |
| 1149 { |
| 1150 this._startNewFrameIfNeeded(); |
| 1151 |
| 1152 var frameId = invalidation.frameId; |
| 1153 this._lastFrameId = frameId; |
| 1154 |
| 1155 if (!invalidation.nodeId && !invalidation.rendererId) { |
| 1156 console.error('Paint invalidation lacks node or renderer information
.'); |
| 1157 console.error(invalidation); |
| 1158 } |
| 1159 |
| 1160 if (this._paintTrackingEvents[frameId] === undefined) |
| 1161 this._paintTrackingEvents[frameId] = []; |
| 1162 this._paintTrackingEvents[frameId].push(invalidation); |
| 1163 }, |
| 1164 |
| 1165 updatePaint: function(paintEvent) |
| 1166 { |
| 1167 this._didPaint = true; |
| 1168 |
| 1169 var frameId = paintEvent.args.data.frame; |
| 1170 var paintId = paintEvent.args.data.paintId; |
| 1171 |
| 1172 paintEvent.styleInvalidationTrackingEvents = []; |
| 1173 paintEvent.layoutInvalidationTrackingEvents = []; |
| 1174 |
| 1175 var styleTrackingEvents = this._styleTrackingEvents[frameId] || []; |
| 1176 var layoutTrackingEvents = this._layoutTrackingEvents[frameId] || []; |
| 1177 var paintTrackingEvents = this._paintTrackingEvents[frameId] || []; |
| 1178 |
| 1179 paintTrackingEvents.forEach(function(paintInvalidation) { |
| 1180 if (paintInvalidation.paintId != paintId) |
| 1181 return; |
| 1182 |
| 1183 // Collect style and layout invalidations that caused this paint. |
| 1184 styleTrackingEvents.forEach(function(invalidation) { |
| 1185 if (invalidation.nodeId == paintInvalidation.nodeId) { |
| 1186 if (paintEvent.styleInvalidationTrackingEvents.indexOf(inval
idation) == -1) |
| 1187 paintEvent.styleInvalidationTrackingEvents.push(invalida
tion); |
| 1188 } |
| 1189 }); |
| 1190 layoutTrackingEvents.forEach(function(invalidation) { |
| 1191 if (invalidation.nodeId == paintInvalidation.nodeId |
| 1192 || invalidation.rendererId == paintInvalidation.rendererId)
{ |
| 1193 if (paintEvent.layoutInvalidationTrackingEvents.indexOf(inva
lidation) == -1) |
| 1194 paintEvent.layoutInvalidationTrackingEvents.push(invalid
ation); |
| 1195 } |
| 1196 }); |
| 1197 }); |
| 1198 }, |
| 1199 |
| 1200 // If there's a new frame, save off all current invalidations. |
| 1201 _startNewFrameIfNeeded: function() |
| 1202 { |
| 1203 if (!this._didPaint) |
| 1204 return; |
| 1205 this._styleTrackingEvents[this._lastFrameId] = undefined; |
| 1206 this._layoutTrackingEvents[this._lastFrameId] = undefined; |
| 1207 this._paintTrackingEvents[this._lastFrameId] = undefined; |
| 1208 this._didPaint = false; |
| 1209 } |
| 1210 } |
OLD | NEW |