Vue-tables-2: Memory Leak

Created on 1 Dec 2017  ·  10Comments  ·  Source: matfish2/vue-tables-2

  • Vue.js version: 2.5.9
  • vue-tables-2 version: 0.6.90
  • consumed using: (browserify/webpack/rollup) webpack
  • FULL error message (including stack trace): None
  • relevant code: None
  • steps for reproducing the issue:

Memory increases if you hide/show (toggle) a vue table many times. I have a JS Fiddle here:
https://jsfiddle.net/hj9ynund/8/
Steps:

  1. Please open up Google Chrome Task Manager hit shift+esc
  2. Load the JS Fiddle URL in Google Chrome
  3. Monitor the active tab and look at the Memory section
  4. On the JS Fiddle clicking on the "Vue Tables 2 Demo" H1 will toggle the hide/show of the vue table. Perform this action about 20 - 50 times. While toggling, keep an eye on the memory that is being used; it should increase.
  5. Stop toggling and wait. The memory never shrinks or gets garbage collected - even after waiting a long period.

In our application users go back and forth from a vue table a good bit and the increasing memory slows the application down dramatically. I'm not sure what is causing it but I suspect the pagination, vuex or the way vnodes are handled.

I have tested this with older versions of both vue and vue-tables-2 locally with the same results.

Thanks

brainstorming bug help wanted

Most helpful comment

I've tracked memory usage using Chrome's Task Manager (Shift + Esc) and it seems like there is indeed some sort of leak, in both the Javascript memory and Memory columns.

The weird thing is that according to vue docs, using v-if should destroy the component properly, just like manually calling this.$destroy:

v-if is “real” conditional rendering because it ensures that event listeners and child components inside
the conditional block are properly destroyed and re-created during toggles.

(https://vuejs.org/v2/guide/conditional.html#v-if-vs-v-show)

I will have to explore this further

All 10 comments

I've tracked memory usage using Chrome's Task Manager (Shift + Esc) and it seems like there is indeed some sort of leak, in both the Javascript memory and Memory columns.

The weird thing is that according to vue docs, using v-if should destroy the component properly, just like manually calling this.$destroy:

v-if is “real” conditional rendering because it ensures that event listeners and child components inside
the conditional block are properly destroyed and re-created during toggles.

(https://vuejs.org/v2/guide/conditional.html#v-if-vs-v-show)

I will have to explore this further

I'm using this guide for Memory analyzing in Chrome Dev tools:
https://developers.google.com/web/tools/chrome-devtools/memory-problems/

If you take a heap snapshot after repro step 4, then search for detached DOM elements it appears that the majority, if not all, of the detached DOM elements are related to pagination. I'm suspecting the pagination is the culprit...

I don't think it's the pagination. I've disabled pagination by using a dropdown instead and the problem persisted. Using the performance bar I recorded memory usage over time and saw a clear pattern where both nodes and listeners are not removed (I have 30 dom listeners and each toggle raises the count by, well, 30). In fact the nodes and listeners form the exact same linear graph.

After some research I found that native DOM listeners (click, change etc.) are NOT removed by vue when the component is destroyed; only custom ones are handled. I finally found a way to traverse the tree from the root to all its descendants and removed all listeners using removeEventListener in the beforeDestroy hook. However, this had no effect whatsoever.

In addition I used the $off method to remove event listeners from both the pagination and table event buses, which are separate vue instances, and therefore not handled when the component is destroyed. Again, this had no effect.

As for the nodes, I am still in the dark as to why they linger on.

I saw there were some bugs related to memory leak in vue's core, but apparently the were fixed long ago, so as of now I'm not sure whether my code is the cause or some limitation/bug in vue

At a quick glance, the leak seems to be caused by https://github.com/matfish2/vue-tables-2/blob/master/lib/v-client-table.js#L75, which is never .$off()ed.

See my comment above:

In addition I used the $off method to remove event listeners from both the pagination and table event buses, which are separate vue instances, and therefore not handled when the component is destroyed. Again, this had no effect.

Actually, I can't reproduce it here: https://jlo7qm246v.codesandbox.io/ (source here: https://codesandbox.io/s/jlo7qm246v?module=%2FApp.vue ).

How did you check it? I was able to reproduce. Go to the Performance tab and start recording. Toggle multiple times and stop recording. You will see that the graph indicates a linear increase in both listeners and nodes.

Seems ok here:

@matfish2 I think you can close this issue. @oWallyson is a colleague of mine and with your updates to vue-pagination and vue-tables-2, our issues are resolved.

Glad to hear :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pmartelletti picture pmartelletti  ·  4Comments

singiankay picture singiankay  ·  4Comments

vesper8 picture vesper8  ·  6Comments

greenpdx picture greenpdx  ·  4Comments

molerat619 picture molerat619  ·  4Comments