We’re evaluating the prospect of refactoring an existing canvas2d app to use canvaskit and utilize webgl.
We have a caching layer that divides the scene into tiles, and use drawImage with the tiles onto the viewport canvas, instead of re-rendering the objects if they haven’t changed (e.g. when panning).
Benchmark: https://stackblitz.com/edit/vitejs-vite-g6sht4?file=config.ts,canvaskit.ts,canvas2d.ts
In the benchmark above, we measured drawing 25*25 = 625 tiles each sized 256*256 px at 1/4 scale. This represents a 6400*6400px scene rendered at 25% zoom to a 1600*1600px viewport (supposed worst case scenario for heavy users). The test machine is a 2021 MacBook with M1 Pro CPU.
We found that in Chrome 112, canvaskit takes ~260ms while canvas2d takes ~160ms. Since chrome is backed by skia I would guess it’s caused by wasm overhead. In Safari 17.3 however, canvaskit also takes ~260ms while canvas2d takes ~200ms.
Note that the console.time() used in benchmarks is only accurate for canvaskit as it includes GPU time. For canvas2d, I had to manually read the performance timeline because I don’t know a way for js to render GPU frame time. Screenshots in appendix.
The only advantage of canvaskit in this case seems to be the ability to use the GPU memory. On an iPhone 14 with iOS 16.7 + Safari 16.6, the above benchmark took ~380ms for canvaskit while canvas2d won’t run due to “Total canvas memory use exceeds the maximum limit (384 MB)”.
For checking performance timeline in the stackblitz link above, click "preview" icon on the top right corner and then "connect" in the new tab. It will provide a standalone window to reload and measure. For Safari it's a bit janky and takes a few tries to work.
So is there something wrong with our usage with canvaskit (e.g calling drawImageRectCubic)? Is there potential for improvements?
Thank you very much!
Appendix:
chrome-canvas2d:

chrome-canvaskit:

safari-canvas2d:
safari-canvaskit:
I did some more testing, it seems in the first flush(), things are getting copied to GPU. Subsequent draws with the same snapshot skimages are very fast (~2ms for canvaskit).
https://stackblitz.com/edit/vitejs-vite-v4ky2m?file=canvaskit.ts,canvas2d.ts,config.ts

I may be wrong guessing they’re copied (e.g. maybe the time was spent painting?) - I’ve found multiple accounts in discussions that it shouldn’t be the case:

I also tried increasing the tile size from 256*256 to 512*512 and reduce the number of tiles. It seems to be faster for both canvas2d (~50ms) and canvaskit(~80ms) - maybe there’re more overhead with more tiles.