Reputation: 2010
When we use the Paint Profiler in Chrome we can see what's being painted. I created a simple example that adds a new div to the page every 3 seconds and here is what is shown as being painted:
But when I use the paint profiler in the Timeline it looks like everything is being repainted:
As shown in the screenshot, on the fifth paint we have 5 calls to drawTextBlob calls. This suggests that all the 5 divs where painted. I was expecting only one.
Can someone shed some light into this?
Upvotes: 1
Views: 927
Reputation: 1979
The exact meaning of "Paint" event has changed over time. It used to be that during Paint the renderer directly updated the layer's bitmap, which was often slow. Back in those days, you would likely find that the painted rectangle matches the area that you actually invalidated (i.e. would be just the last line in your case), as you probably expect.
Present implementation of Chrome's rendering subsystem performs rasterization either on other threads (in an attempt to keep things off the main thread which is busy enough with JavaScript execution, DOM layout and lots of other things) or on GPU (check out "Rasterization" and "Multiple raster threads" in chrome://gpu if you're curious to know what's the current mode on your platform). So the "Paint" event that you see on the main thread just covers recording a log of paint commands (i.e. what you see on the left pane of the Paint Profiler), without actually producing any pixels -- this is relatively fast, and Chrome chooses to re-record the entire layer so it can later pick what part of it to rasterize (e.g. in an anticipated case of scrolling) without going to main thread again, which is likely to be busy by running JavaScript or doing a layout.
Now if you switch Timeline into Flame Chart mode (right icon near "View" label in Toolbar), you'll see "Rasterize Paint" event which is actual rasterization -- Chrome picks the paint command log recorded during Paint event on the main thread and re-plays it producing actual pixels for a fragment of the layer. You can see what part of the layer was being rasterized and the Paint Profiler for this part when you select "Rasterize Paint". Note that there are many small Rasterize Paint events for different fragments, possible on different threads, but they still all have the entire log (i.e. 5 drawTextBlob commands in your example). However, those paint commands that do not affect the fragment being rasterized will be culled as they fall outside of the fragment's clip rectangle and hence won't have noticeable effect on rasterization time.
Then, you'll probably notice that the fragments being rasterized are still larger than the area you've actually invalidated. This is because Chrome manages rasterized layers in terms of tiles, small rectangular bitmaps (often 128 x 128, but may vary by platform), so that for large layers (e.g. pages much longer than viewport), only the parts visible in the viewport could be stored on the GPU (which often has a limited memory) and the parts that suddenly become visible as a result of scrolling could be uploaded fast.
Finally, the parts that you see highlighted with green as a result of you ticking "Show Paint rectangles" in Rendering options, are technically an "invalidation" rectangles -- i.e. that's the areas of your page that have really changed as a result of changed layout/styles etc. These areas are what you really as an author can directly affect, but as you see, Chrome will likely paint and rasterize more than that, mostly out of concerns of managing the scrolling of large pages efficiently.
Upvotes: 6