Bug 242394

Summary: [CoordinatedGraphics] Cache and reuse image-based backing stores
Product: WebKit Reporter: Miguel Gomez <magomez>
Component: WebKitGTKAssignee: Zan Dobersek (Reviews) <zdobersek>
Status: RESOLVED FIXED    
Severity: Normal CC: bugs-noreply, pawel.lampe, zan
Priority: P2    
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
WIP patch
none
WIP patch
none
WIP patch none

Description Miguel Gomez 2022-07-06 09:27:21 PDT
This was reported downstream for 2.28 but it's happening on upstream ToT as well.

Before we switched to use nicosia, several CoordinatedGraphicsLayers that would be using the same image as imageBacking would share the same buffer with the image content. This way we would only render and send to the composition stage a single buffer, and all the TextureMapperLayers would use it during the composition.

But with the current implementation using nicosia this doesn't happen anymore. Each CoordinatedGraphicsLayer will use its own buffer containing the image as the imageBacking. Due to this, several buffers with the same image will be created and passed to the composition stage, increasing the used memory a lot.

There's a very common scenario when an application uses a very big image that contains several smaller images (sprites), and the application will, for example, set parts of that big image as the background for several divs, so each div shows one of the sprites. If those divs have their own GraphicsLayer (because of hw acceleration reasons), before nicosia there would be a single buffer containing the big image and that would be used by all the GraphicsLayers. But nowadays each layer will use a buffer containing the big image, which is a waste of memory. Also this happens at the same time we're rendering the backingStore contents, so we are already at point where the memory usage is high, potentially triggering oom kills for the excessive memory consumption.

This happens if you visit https://sky.play.works/service/apps/portal/index.html. After the initial page with the loading progress bar, a page with the list of games is shown. All of the game covers are stored in a single image with size 1409x986, and each game shown is a div with part of that image as the background. In this case, the large image with all the covers is rendered into more than 20 buffers, creating a huge memory spike that should not be necessary. (be sure to maximize the browser window before loading the page, otherwise for some reason the images loaded will be smaller).

We should implement back some system to share imageBackings buffers among the CoordinatedGraphicsLayers that are using the same image to avoid this.
Comment 1 Zan Dobersek 2022-07-13 07:10:52 PDT
Created attachment 460858 [details]
WIP patch

Still needs the caching functionality.
Comment 2 Zan Dobersek 2022-07-21 06:16:49 PDT
Created attachment 461112 [details]
WIP patch

Now with caching in different parts, but not yet cleaned up and validated.
Comment 3 Pawel Lampe 2022-08-12 04:19:45 PDT
Tested WIP change using WPE build with MiniBrowser on play.works portal and the Nicosia::Buffer-related memory usage went down from 154MB to 22MB. It's very promising result.
Comment 4 Zan Dobersek 2022-08-24 00:49:01 PDT
Created attachment 461836 [details]
WIP patch

This additionally moves out the CPU buffer when the backing store is created, avoiding keeping the buffer around after the backing store is already active and cached.
Comment 5 Zan Dobersek 2022-08-25 06:21:55 PDT
Pull request: https://github.com/WebKit/WebKit/pull/3652
Comment 6 EWS 2022-08-25 23:06:46 PDT
Committed 253807@main (487411cb6083): <https://commits.webkit.org/253807@main>

Reviewed commits have been landed. Closing PR #3652 and removing active labels.