Pdf.js: Rendering hangs the UI for large images because webworkers are not setup correctly

Created on 10 Feb 2020  路  4Comments  路  Source: mozilla/pdf.js

Dear PDF.JS contributors,

Sometimes, a pdf contains big images inside some pages and when an app makes the call: pdfPage.render(renderContext); the UI hangs or freezes for few milliseconds.

I am using range requests so I have enabled disableAutoFetch and disableStream.

For example here it's quite complex UI but I think the causes of freezing is the render method with this options enabled: https://app.fays.io/d8603488-1c8a-44d4-af04-c93e22170514 (where as it works fine with https://app.fays.io/6dc95ad2-45c9-4012-b864-eeaa8ca27599, and with some compression: https://app.fays.io/fd7be64d-ec78-4731-9dff-7b9c8088acf9) [you may download both files using the developper tool/network/download]

I did not test with these options using the integrated viewer of PDF.JS but if it works with this file, how do you manage to succeed where I am stuck 馃憥

I have found that the page is downloaded when render is called but not after getPage. Why ?

Beside, I would like to know whether is it possible to render to a canvas in multiple steps: that is to render the images, then the text for example.

Thank you, A.

Firefox:
Capture d鈥檈虂cran 2020-02-10 a虁 23 28 45

Chrome:

Capture d鈥檈虂cran 2020-02-10 a虁 23 20 03

Is the following a good start ? How does it works ?
https://github.com/mozilla/pdf.js/blob/10be0997a78835fb04f0d992dd3d38118c4eb176/web/pdf_page_view.js#L635-L655

1-other

Most helpful comment

There's one additional, and extremely important point evident from the console logs in your examples:

Warning: Setting up fake worker.

This suggests that you either didn't setup workers correctly (e.g. you may be missing pdfjsLib.GlobalWorkerOptions.workerSrc), or that you manually loaded the pdf.worker.js file on main-thread (which you should never do).

You really need to use Web Workers, such that the heavy parsing of the PDF document doesn't block/hang the main-thread where rendering happens. When Web Workers are disabled, general performance and UI responsiveness will suffer and it's thus unlikely that trying to use the RenderTask.onContinue functionality will help much until you've enabled Workers.

All 4 comments

The above is a good start. You can pause rendering each time pdf.js does a certain amount of work. https://github.com/mozilla/pdf.js/blob/10be0997a78835fb04f0d992dd3d38118c4eb176/src/display/api.js#L2684

You'll probably want to use a setTimeout to call cont callback to give the main event loop a chance to run.

There's one additional, and extremely important point evident from the console logs in your examples:

Warning: Setting up fake worker.

This suggests that you either didn't setup workers correctly (e.g. you may be missing pdfjsLib.GlobalWorkerOptions.workerSrc), or that you manually loaded the pdf.worker.js file on main-thread (which you should never do).

You really need to use Web Workers, such that the heavy parsing of the PDF document doesn't block/hang the main-thread where rendering happens. When Web Workers are disabled, general performance and UI responsiveness will suffer and it's thus unlikely that trying to use the RenderTask.onContinue functionality will help much until you've enabled Workers.

This suggests that you either didn't setup workers correctly (e.g. you may be missing pdfjsLib.GlobalWorkerOptions.workerSrc), or that you manually loaded the pdf.worker.js file on main-thread (which you should never do).

@Snuffleupagus Yes indeed Sir, the UI doesn't block with webworkers setup correctly 馃

With Typescript and webpack, I used to run pdfjsLib.GlobalWorkerOptions.workerSrc and import * as pdfjs from 'pdfjs-dist';

Instead webworkers finally run outside the main thread using import * as pdfjs from 'pdfjs-dist/webpack';. According to the documentation, the easiest way to setup web workers is https://github.com/mozilla/pdf.js/tree/master/examples/webpack.

You'll probably want to use a setTimeout to call cont callback to give the main event loop a chance to run.

@brendandahl Strangely, the script calls onContinue only once. It does runs through it after downloading the page.

Using web workers is key here to prevent the UI from freezing. It's not easily possible to render the PDF file in a different order, at least it's not something that PDF.js supports.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dmisdm picture dmisdm  路  3Comments

AlexP3 picture AlexP3  路  3Comments

zerr0s picture zerr0s  路  3Comments

brandonros picture brandonros  路  3Comments

liuzhen2008 picture liuzhen2008  路  4Comments