Chromium Code Reviews| Index: Source/devtools/front_end/timeline/TracingTimelineModel.js |
| diff --git a/Source/devtools/front_end/timeline/TracingTimelineModel.js b/Source/devtools/front_end/timeline/TracingTimelineModel.js |
| index 2cd5efd8681d9011c0faab9ec83ef93ac7d996b8..fa2894db584fef2d2fc56e0792f892f09b78a228 100644 |
| --- a/Source/devtools/front_end/timeline/TracingTimelineModel.js |
| +++ b/Source/devtools/front_end/timeline/TracingTimelineModel.js |
| @@ -47,6 +47,11 @@ WebInspector.TracingTimelineModel.RecordType = { |
| ScrollLayer: "ScrollLayer", |
| CompositeLayers: "CompositeLayers", |
| + StyleRecalcInvalidationTracking: "StyleRecalcInvalidationTracking", |
| + LayoutInvalidationTracking: "LayoutInvalidationTracking", |
| + LayerInvalidationTracking: "LayerInvalidationTracking", |
| + PaintInvalidationTracking: "PaintInvalidationTracking", |
| + |
| ParseHTML: "ParseHTML", |
| TimerInstall: "TimerInstall", |
| @@ -138,7 +143,9 @@ WebInspector.TracingTimelineModel.prototype = { |
| WebInspector.TracingModel.ConsoleEventCategory |
| ]; |
| if (captureCauses) { |
| - categoriesArray.push(disabledByDefault("devtools.timeline.stack")); |
| + categoriesArray = categoriesArray.concat([ |
| + disabledByDefault("devtools.timeline.stack"), |
| + disabledByDefault("devtools.timeline.invalidationTracking")]); |
|
caseq
2014/10/15 16:24:52
make the latter conditional on Runtime.experiments
pdr.
2014/10/16 07:46:47
Great catch. This was a bad merge on my part :(
|
| if (Runtime.experiments.isEnabled("timelineJSCPUProfile")) { |
| this._jsProfilerStarted = true; |
| this._currentTarget = WebInspector.context.flavor(WebInspector.Target); |
| @@ -475,6 +482,7 @@ WebInspector.TracingTimelineModel.prototype = { |
| this._sendRequestEvents = {}; |
| this._timerEvents = {}; |
| this._requestAnimationFrameEvents = {}; |
| + this._invalidationTracker = new WebInspector.InvalidationTracker(); |
| this._layoutInvalidate = {}; |
| this._lastScheduleStyleRecalculation = {}; |
| this._webSocketCreateEvents = {}; |
| @@ -591,6 +599,46 @@ WebInspector.TracingTimelineModel.prototype = { |
| this._lastRecalculateStylesEvent = event; |
| break; |
| + case recordTypes.StyleRecalcInvalidationTracking: |
| + this._invalidationTracker.addInvalidation({ |
| + type: recordTypes.StyleRecalcInvalidationTracking, |
| + frameId: event.args.data.frame, |
|
caseq
2014/10/15 16:24:53
here and below: we use object["field"] syntax unle
|
| + nodeId: event.args.data.nodeId, |
| + nodeName: event.args.data.nodeName, |
| + reason: event.args.data.reason, |
| + callstack: event.args.data.callstack |
| + }); |
| + break; |
| + |
| + case recordTypes.LayoutInvalidationTracking: |
| + this._invalidationTracker.addInvalidation({ |
| + type: recordTypes.LayoutInvalidationTracking, |
| + frameId: event.args.data.frame, |
| + nodeId: event.args.data.nodeId, |
| + nodeName: event.args.data.nodeName, |
| + callstack: event.args.data.callstack |
| + }); |
| + break; |
| + |
| + case recordTypes.LayerInvalidationTracking: |
| + this._invalidationTracker.addInvalidation({ |
| + type: recordTypes.LayerInvalidationTracking, |
| + frameId: event.args.data.frame, |
| + paintId: event.args.data.paintId, |
| + reason: event.args.data.reason |
| + }); |
| + break; |
| + |
| + case recordTypes.PaintInvalidationTracking: |
| + this._invalidationTracker.addInvalidation({ |
| + type: recordTypes.PaintInvalidationTracking, |
| + frameId: event.args.data.frame, |
| + nodeId: event.args.data.nodeId, |
| + nodeName: event.args.data.nodeName, |
| + paintId: event.args.data.paintId |
| + }); |
| + break; |
| + |
| case recordTypes.InvalidateLayout: |
| // Consider style recalculation as a reason for layout invalidation, |
| // but only if we had no earlier layout invalidation records. |
| @@ -635,6 +683,7 @@ WebInspector.TracingTimelineModel.prototype = { |
| break; |
| case recordTypes.Paint: |
| + this._invalidationTracker.didPaint(event); |
| event.highlightQuad = event.args["data"]["clip"]; |
| event.backendNodeId = event.args["data"]["nodeId"]; |
| var layerUpdateEvent = this._findAncestorEvent(recordTypes.UpdateLayer); |
| @@ -1103,3 +1152,88 @@ WebInspector.TracingTimelineSaver.prototype = { |
| */ |
| onError: function(reader, event) { }, |
| } |
| + |
| +/** |
|
caseq
2014/10/15 16:24:53
@constructor
|
| + * Track invalidation events across frames. |
| + */ |
| +WebInspector.InvalidationTracker = function() |
|
caseq
2014/10/15 16:24:53
I wonder if we should make it a part of _processEv
pdr.
2014/10/16 07:46:48
Would you mind if we punt on this for now? I'm not
|
| +{ |
| + this._invalidationEvents = []; |
| + this._lastPaintWithLayer = undefined; |
| + this._didPaint = false; |
| +} |
| + |
| +WebInspector.InvalidationTracker.prototype = { |
| + |
| + addInvalidation: function(invalidation) |
|
caseq
2014/10/15 16:24:53
please annotate!
|
| + { |
| + this._startNewFrameIfNeeded(); |
| + if (!invalidation.nodeId && !invalidation.paintId) { |
| + console.error('Invalidation lacks node information.'); |
|
caseq
2014/10/15 16:24:53
double quotes, please!
|
| + console.error(invalidation); |
| + } |
| + |
| + // Record the paintIds for style recalc or layout invalidations. |
| + // FIXME: This O(n^2) loop could be optimized with a map. |
| + if (invalidation.type == WebInspector.TracingTimelineModel.RecordType.PaintInvalidationTracking) { |
| + this._invalidationEvents.forEach(function(invalidationToUpdate) { |
| + if (invalidationToUpdate.nodeId != invalidation.nodeId) |
|
caseq
2014/10/15 16:24:52
!==
|
| + return; |
| + switch (invalidationToUpdate.type) { |
|
caseq
2014/10/15 16:24:52
Can we defer making it a "switch" till we have to
pdr.
2014/10/16 07:46:48
Looks like 'switch' and 'if/else' are the same the
|
| + case WebInspector.TracingTimelineModel.RecordType.StyleRecalcInvalidationTracking: |
| + invalidationToUpdate.paintId = invalidation.paintId; |
| + break; |
| + case WebInspector.TracingTimelineModel.RecordType.LayoutInvalidationTracking: |
| + invalidationToUpdate.paintId = invalidation.paintId; |
| + break; |
| + } |
| + }); |
| + } else { |
| + this._invalidationEvents.push(invalidation); |
| + } |
| + }, |
| + |
| + didPaint: function(paintEvent) |
|
caseq
2014/10/15 16:24:53
please annotate.
|
| + { |
| + this._didPaint = true; |
| + |
| + // If a paint doesn't have a corresponding graphics layer id, it paints into it's parent so |
|
caseq
2014/10/15 16:24:53
s/it's/its/
pdr.
2014/10/16 07:46:47
Stupid English!
Fixed.
|
| + // add an effectivePaintId to these events. |
| + // FIXME: The parent layer is assumed to be the last paint event that had a layerId set. Is that right? |
|
caseq
2014/10/15 16:24:53
Apparently yes, as we never have nested layer pain
|
| + var layerId = paintEvent.args.data.layerId; |
|
caseq
2014/10/15 16:24:53
paintEvent.args["data"][layerId"]
|
| + if (layerId) |
| + this._lastPaintWithLayer = paintEvent; |
| + |
| + if (!this._lastPaintWithLayer) { |
| + console.error("Failed to find the paint container for a paint event."); |
| + return; |
| + } |
| + |
| + var effectivePaintId = this._lastPaintWithLayer.args.data.nodeId; |
| + this._processPaint(paintEvent, effectivePaintId); |
| + }, |
| + |
| + _processPaint: function(paintEvent, effectivePaintId) |
|
caseq
2014/10/15 16:24:53
inline into didPaint?
|
| + { |
| + var frameId = paintEvent.args.data.frame; |
| + |
| + this._invalidationEvents.forEach(function(invalidation) { |
| + if (invalidation.paintId == effectivePaintId && invalidation.frameId == frameId) { |
|
caseq
2014/10/15 16:24:52
s/==/===/g
|
| + if (!paintEvent.invalidationTrackingEvents) |
| + paintEvent.invalidationTrackingEvents = []; |
| + paintEvent.invalidationTrackingEvents.push(invalidation); |
| + } |
| + }); |
| + }, |
| + |
| + _startNewFrameIfNeeded: function() |
| + { |
| + if (!this._didPaint) |
| + return; |
| + |
| + // Prepare for the next frame. |
| + this._invalidationEvents = []; |
|
caseq
2014/10/15 16:24:52
Looks like if we add new state variable, we'll be
pdr.
2014/10/16 07:46:48
Great point. Factored out into _initializePerFrame
|
| + this._lastPaintWithLayer = undefined; |
| + this._didPaint = false; |
| + } |
| +} |