Huge memory leak - React

Hello, we have been using @pdftron/pdfjs-express-viewer since last week and we noticed a memory leak.

We encountered this problem while trying to use the Viewer in a Modal that unmounts everytime you close it.

Reproduce method:

  1. Open htop or a similar system to monitor your memory.
  2. Then go to PDF.js Viewer Demo | PDF.js Express
  3. Now, alternate between the demo page and the pricing page.
  4. every time you enter the demo page, your memory will increase.

We are using the getInstance()
We think dispose() is not gc everything.

Hi Carlos1,

Do you have any addEventListeners()?

Ensure you run removeEventListener on any event listeners you have added, these will hold onto the instance in memory if not removed.

As for our demo, we don’t run dispose on our instance since we don’t open/reopen it in the same page.

Best regards,
Tyler

Hi @tgordon

Thank you for your answer, we are running dispose on our side but it doesn’t change anything, so we believe this is a bug from the viewer.

I personally spent the whole day today trying to find a solution for this. Im SUPER available to provide you with more info.

Yes, we have two event listeners, but even when I remove them, we still have the same issue.

This is quite a critical bug for us since after a few uses this crashes the whole browser.

Hi CarlosVergikosk,

  • Can you please provide a sample application that reproduces the issue?
  • And by chance are you calling display: none on the viewer?
  • Or can you provide the code that you use to show/hide/remove the viewer from the webpage?

Best regards,
Tyler

Hi @tgordon ,
Answer to 1: Not really, but I can explain our use-case:

We have a right tab panel that shows the viewer.
We allow our users to open a modal with other documents at the same time.

The modal destroys its content on close, meaning it will create a new web viewer instance on each use.

Answer to 2: No, we totally unmount the viewer from our app.

Answer to 3: Yes, here it is


const instance = getInstance()

React.useEffect(() => {
        return () => {
            if (instance) {
                instance.UI.closeDocument()
                instance.UI.dispose()
            }
        }
    }, [instance])

We tried to call all the methods available after each destroy but there are accumulations of data in memory on every creation of a new instance.

After a few openings, chrome crashes.

The solution of reusing a viewer is not really convenient for us.
Ideally, the disposal function would erase everything in order to keep the memory healthy.

Best,
Carlos

Hi @tgordon, do you have any news?

Hi Carlos,

The implication of checking
if(instance)
means you are storing the instance object, therefore, calling

instance.UI.closeDocument()
instance.UI.dispose()

Does not delete the instance from memory. You have to dereference the instance by (if you are using state to store the instance):

setInstance(null)`

After calling closeDocument and dispose

Best regards,
Tyler

Hi @tgordon, im using React and yes I’m using a local state to keep track of it, but the state is unmounted and so removed together with the viewer. I believe the WebViewer() is actually the problem.

I actually proved it in my example on the topic description, you have the same problem with your pdfjs viewer demo.

Hi CarlosVergikosk,

We will add this to our backlog to be prioritized by our product team. Thank you for your patience.

Best regards,
Tyler

@tgordon Thank you, i hope this can be done relatively quickly as it is very important for us.

7npxae