Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detached node memory leak #167

Open
chronicadventure opened this issue Dec 27, 2024 · 8 comments
Open

Detached node memory leak #167

chronicadventure opened this issue Dec 27, 2024 · 8 comments

Comments

@chronicadventure
Copy link

Hello again. I've run into a problem where either your component or the underlying pdf.js is causing a memory leak by leaving the entire contents of a rendered pdf as detached nodes. I've included a link to a minimum reproduction. It's a simple nuxt project with the only dependency being the tato30/vue-pdf package. I've also included a screen cap in the git repo showing the issue. I would love to try and fix it and make a pr but I am not a strong front end developer and it would likely take me days to even figure out how to navigate the vue component project itself

Here is the repo:
https://github.com/chronicadventure/tato30-vue-pdf-mem-leak (make sure to run it on localhost:3000 as my storage account allows CORS requests from here)

the screen cap is in the repo

@chronicadventure
Copy link
Author

Also as a side note, the dedicated workers are still not being terminated in the latest version. I remember seeing that you added the termination code a while back. Check my unmounted block. I am terminating the web worker along with any other assets being held onto by pdf js by doing this:

if (pdf.value && typeof pdf.value.destroy === 'function') {
  console.log('Destroying PDF document');
  await pdf.value.destroy();
}

@chronicadventure
Copy link
Author

chronicadventure commented Dec 28, 2024

More info here. I went ahead and cloned this repo and ran into some interesting findings. If I tried to reproduce in your playground by just unmounting and mounting the VuePdf component using a button, there were never any memory issues. The workers got cleaned up as well.

Once I put everything behind vue router (meaning one page would be a blank page, and the other would hold the pdf) then workers would be left unclosed when I changed pages. I could not however reproduce my original issue which opened this issue with. There indeed were detached nodes; however, they did not multiple with each reload of the pdf like they did in my nuxt reproduction. Here is the forked branch if you want to take a look

https://github.com/chronicadventure/vue-pdf/tree/debug/memory-issues

the memory issues seem to only happen when changing routes for some reason.

@bennyzen
Copy link

Confirmed. Navigating away keeps memory fully allocated, even using the above described unmounted block. What am I supposed to do to free memory?

@chronicadventure
Copy link
Author

I haven't had the chance to try it yet but I had the idea of wrapping my entire page in an identifier and using plain old js to fetch it and remove it from the dom on unmount. It's ugly and goes against vue standards but hopefully it works.

@chronicadventure
Copy link
Author

chronicadventure commented Dec 29, 2024

The above idea did not work. I did however reproduce the memory leak without vue-pdf so I don't think this is tato's library at all anymore. I've found an issue on the nuxt project that seems very similar but not sure there's a fix yet.

nuxt/nuxt/#15239

for reference, here is my latest branch that reproduces this issue without vue-pdf

https://github.com/chronicadventure/tato30-vue-pdf-mem-leak/tree/leak-without-pdf

@chronicadventure
Copy link
Author

chronicadventure commented Dec 29, 2024

Actually I take my comment above back. It's definitely something in the vue-pdf component. Take a look at the two screen shots here. The first one is me navigating from home to the pdf page over and over. You can see the blue spikes are all allocated memory from when I open the pdf. Notice none of the blue spikes do not have gray bars which means they were not GC-ed.

Screenshot 2024-12-29 at 4 21 44 PM

After a while my tab hit 3gb and froze out.
Screenshot 2024-12-29 at 4 22 31 PM

Now take a look at the memory allocations and gc collections when visiting between the home page and the large node page
Screenshot 2024-12-29 at 4 23 34 PM

It may take a few nav cycles but the gc eventually destroys the old allocations.

Furthermore, if you take a heap snapshot and just comb through some of the heaver retained assets, you can see lots of references to the vue-pdf component. I will continue diving into this and see if I can't figure out what's going on.

Screenshot 2024-12-29 at 4 33 26 PM Screenshot 2024-12-29 at 4 33 00 PM Screenshot 2024-12-29 at 4 32 25 PM Screenshot 2024-12-29 at 4 31 49 PM

@TaTo30
Copy link
Owner

TaTo30 commented Dec 30, 2024

Some versions ago the vue-pdf component would destroy the worker automatically, but after some issues with the unpredictable behaviour was added as a optional prop named auto-destroy

onUnmounted(() => {
// Abort all network process and terminates the worker
if (props.autoDestroy) props.pdf?.destroy();
});

I've tested with your repo (the "mem-leak" one) and it seems to cleanup properly but there are some cases that the worker is not destroyed, I am not sure if by pdf.js or the way on how Nuxt navigates the routes.

This the edit I made

<template>
    <h3>
        <NuxtLink :to="'/'">
            Go home
        </NuxtLink>
        <div v-for="(page, index) in pages">
          <!-- Auto Destroy the worker -->
            <VuePDF :pdf="pdf" :page="page" auto-destroy></VuePDF>
        </div>
       
    </h3>
</template>

<script setup>

import { VuePDF, usePDF } from '@tato30/vue-pdf';


const { pdf, pages } = usePDF('https://retailgptstorage.blob.core.windows.net/retaildocs/walmart-supply-chain-packaging-guide-20240131.pdf');

</script>

@chronicadventure
Copy link
Author

chronicadventure commented Jan 3, 2025

I've been unable to fix nor track down the exact cause of this. I ended up working around the issue. The memory only leaks when the route is changed so I changed my nav bar links to run an action that sets the window.location to the route the nuxt link would have routed to. This only happens when a pdf is in view, otherwise nuxt links remain. This forces a full navigation which wipes the memory. It's not the best UX but having a splash screen makes it almost seem less.

I hope nuxt finds the issue to this, this is a pretty nasty bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants