Render performance improvements using ImageBitmap#490
Render performance improvements using ImageBitmap#490Schibum wants to merge 2 commits intoembedpdf:mainfrom
Conversation
|
@Schibum is attempting to deploy a commit to the OpenBook Team on Vercel. A member of the Team first needs to authorize it. |
|
This looks really promising. I'm looking forward to the continuation of this. |
|
Cleaned up now, removed renderMode and just made bitmap the new behaviour. Added other framework adapters. Tested them manually, but I'm not familiar enough with the codebase to be really confident about all edge cases (e.g. vue tile-img.vue has clearing behavior noted as critical which does not seem mirrored for other frameworks). Preview of snippet of current version is at https://45ea77f1.embedpdf-perf-playground.pages.dev Essentially adds bitmap based render methods to render-plugin. Kept blob-based methods to keep scope of changes somewhat limited (e.g. capture-plugin is unchanged). The bitmap rendering just uses the existing raw rendering worker methods, but wires though the critical priority flag for full-page renders. Added collectTransferables to wire worker data back without additional copying. Then using bitmaps in RenderLayer(s), plugin-tiling and plugin-thumbnail, while adding a small LRU cache for thumbnail to avoid re-renders when closing/opening the sidebar. Added Task.map() to reduce task mapping boilerplate - could be reverted if desired, not needed for the scope of this. |
Experimental implementation of using
createImageBitmap()/ canvas for rendering instead ofconvertToBlob()/ img.Mainly meant as basis for discussion for now. Still needs some work/clean, depending on the direction. Idea has been discussed in #105 before.
Adds a
renderMode: 'blob' | 'bitmap'option to RenderPlugin, which switches between the existing approach and the ImageData code path.Added performance measurements for RenderLayer (RenderLayer.blob.render / RenderLayer.bitmap.render) round-trip until paint, and same for TileImg. Along with measurements for
createImageData()andconvertToBlob()(PdfEngine.encodeImage.encode()).An overlay in the snippet viewer (
<PerfOverlay/>) shows the performance data for easy testing on (mobile) devices.ImageBitmap mode (the
?bitmapquery enables it):https://embedpdf-perf-playground.pages.dev/?bitmap
Blob mode:
https://embedpdf-perf-playground.pages.dev/
Benefits of createImageBitmap() seem to depend on device, browser and pdf file. On fast devices the the bitmap benefit seems barely noticeable (unsurprisingly since image encode/decode is just some tens ms and paid for in a separate thread).
This is from scrolling down/up on the default NASA pdf:
Chrome / M1 Max:

Firefox M1 Max:


I also tested on a few other devices, including two older ones. On an 7th gen iPad, the added imageEncode delay is
~200+ms, similar on an ancient Samsung Chromebook Plus7th gen iPad:


M5 iPad:


iPhone 14 / Pixel 10 Pro are somewhere in-between (40-60ms image encode).
There's probably also additional GC cost for the blob path which is harder to measure.
For Thumbnails the downside of ImageBitmaps is that they are much larger, so caching (at least in an unbound way like done for Blobs right now) would probably make less sense. One could either just not cache at all, use an LRU cache limited to a few pages, or just continue using imgs for thumbnails. Demo just re-renders on sidebar re-opening with no caching.
Not sure if there's a use-case for keeping both methods - at least for RenderLayer/TileLayer. Branch currently contains a few duplications and missing vue/svelte components, happy to clean it up if this seems like a way forward.
RenderPlugin and Image encode worker could probably be simplified accordingly too if thumbnails are switched to bitmap as well - but that'd be a more breaking change.