Gecko:OffMainThreadPainting

From MozillaWiki
Revision as of 03:47, 17 January 2013 by Mattwoodrow (talk | contribs)
Jump to navigation Jump to search

Problem

Painting is slow. On complex, dynamic pages, we spend a large amount of CPU time rasterizing the page which blocks the main thread from being responsive. Ongoing work to reduce the amount of painting done (DLBI), and improve the speed of painting are helping with this, but being able to offload the entirety of this work to another thread will be a significant gain.

Goals

  • Improve painting throughput performance (increase frames per second drawn to the screen)
  • Reduce the load on the main thread to improve responsiveness and reduce jank.

Proposed solution

Modify our current display item list items to be entirely self contained, such that they only access main-thread data during construction (or an explicit finalization pass). We can then pass the entire tree across to the painting thread to do all visibility analysis, layer building and ThebesLayer painting. This would require that ownership and access to FrameLayerBuilder and Layers become painting-thread only, instead of main-thread only as they currently. Compositing then happens on yet another thread via off-main-thread compositing (OMTC - Bug 598873).

Alternatives

Chrome's proposed solution to the same problem (https://sites.google.com/a/chromium.org/dev/developers/design-documents/impl-side-painting) is lower level. Rather than using high-level drawable objects (display items), they plan to serialize a stream of skia drawing commands. This lets them store the entirety of a layer's content (within reason), not just restricted to areas that are currently visible. They can then rasterize newly exposed content during scrolling without accessing the main thread, and without the large memory trade-off of pre-rendering areas that are expected to be scrolled into view. They can also dynamically re-rasterize areas of layers at a new resolution or quality setting without requiring main thread access.

This solution probably will give better results (less checkerboarding and/or jank) when fling scrolling a static page, but doesn't benefit as much for dynamic pages that require modifications to the drawing stream.

Plan

  • Build infrastructure to run a painting thread, and ship display items across to it.
  • Fix a few basic DisplayItem types to not require main-thread access, such that we can run basic reftest style pages off main-thread.
    • Ideally it would be nice to have dynamic fallback to main-thread painting if other display item types are encountered, but not necessary.
  • Start porting the remainder of the display item types to not require main-thread access
    • Each display item should be a fairly self contained chunk of work, so we can parallelize this stage well

Prerequisites

  • OMTC finished and enabled on all platforms
  • It would be worthwhile to wait for the Layers refactoring to be completed to avoid too many conflicts.

Details and Specifics

Need to find all external users of Layers and FrameLayerBuilder and find a way to avoid direct access.

  • Images/ImageContainer
  • Canvas
  • GetDedicatedLayerFor
  • InvalidateAllLayers
  • DLBI cached display item data
  • ?

Can we prevent accidental access of main-thread data from the painting thread? Both during the transition process, and for new code added in the future.

  • We can pepper nsIFrame methods with IsMainThread() assertions, this would hopefully catch a large proportion of potential issues.
  • ?

We need to investigate throttling/scheduling for the main-thread/painting-thread so that they don't end up too out of sync.

Invalidation (and thus MozAfterPaint regions) will now be happening on the painting-thread, so we need to pass that back to fire callbacks.

Testing

I don't imagine us needing anything specific with regards to testing. Since this is an intermediate stage between layout and compositing, existing reftests (that are testing OMTC) should also be fine for testing correctness. Our existing performance testing infrastructure shouldn't be affected. It's possible that page-load times may regress because of the added overhead of changing threads.

Display Item Conversion

Backgrounds - nsCSSRendering

  • A decent block of code, but should be fairly easy apart from images.

Images

  • Imagelib only supports main-thread access currently, need to find a way to ship the images (preferably without blocking on decoding) to the painting thread.

Text

  • Unknown

Style Data

  • Can we allow access to style structs from the painting thread?

SVG Images

-moz-element

Further Work

Retaining the display list on the painting thread, and adding interactions with the asynchronous scrolling code. This would let us render new content as we scroll (without interacting with the main thread) and give us parity with Chrome's approach during scrolling.