[webkit-dev] Canvas performance and memory usage

David Hyatt hyatt at apple.com
Tue Aug 3 13:51:29 PDT 2010

This would probably have to be verified, but I believe CG uses copy-on-write semantics when creating an image from a bitmap context.  Therefore I suspect this is not a performance problem with CG just because of smarts in the underlying CG implementation.  Basically image() is a "cheap" call for CG, and creating/destroying images over and over when frequent drawing happens is not expensive.  However I'm not 100% sure about this.

I think the fact that the image has to be manually cleared from the ImageBuffer is part of the problem.  I think we should redesign ImageBuffer::image() so that every time it's called you can guarantee that you're getting an accurate reflection of the contents of the image buffer.

I notice that Qt added imageForRendering() and felt they could not use image() for some reason.  I'd be curious if a Qt expert could weigh in on that, since maybe with a redesign a separate call would not be needed.

Here's a basic suggestion for how to improve this:

(1) Make sure your port does a lightweight wrapping of the ImageBuffer into an Image and does not do a copy.  It's debatable whether this Image really even needs to be cached if the creation operation is really lightweight.  I think people copied the CG implementation I wrote where I wasn't 100% sure if I needed to cache or not, and that has created some of the confusion.

(2) If anyone accesses the GraphicsContext of an ImageBuffer and we do cache the Image, maybe just assume they're going to draw and clear out the image.

Anyway, I'd definitely file a bug.

(hyatt at apple.com)

On Aug 3, 2010, at 3:20 PM, Christophe Public wrote:

> Hi,
> There is a performance hit when using HTML canvas when using ImageBufferCairo:
> - As soon as something is rendered in the canvas, the HTMLCanvasElement::willDraw method is called which in turn calls clearImage on the imageBuffer if one is already present. 
> - When the render tree is traversed (HTMLCanvasElement::paint gets called), the image containing the canvas is drawn using GraphicsContext::drawImage. Unfortunately, ImageBuffer::image() (in BufferImageCairo.cpp) allocates a new surface, and copies the image surface into it. When very frequent updates are done in the canvas, this double buffering causes significant performance degradation that worsens with large canvas sizes. In addition, the extra memory consumption can become quite expensive especially on embedded devices.
> Can anybody explain why this double buffering is necessary for ImageBuffer specifically for the Cairo port? 
> We are looking at disabling the double buffering at least for the canvas because of both performance and memory issues. It would also be nice to disable it for images as well but we would like to understand why in the first place it was added. Note that a code comment states "This seems silly, but is the way the CG port works: image() is intended to be used only when rendering is complete."
> Any suggestion on how to fix this issue is welcome. If it is considered a bug, then I will create a bug as well to keep track of it.
> Regards,
> Christophe
> _______________________________________________
> webkit-dev mailing list
> webkit-dev at lists.webkit.org
> http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev

More information about the webkit-dev mailing list