WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.07k stars 113 forks source link

hyperHTML memory leaks / detached DOM nodes #242

Closed jaschaio closed 6 years ago

jaschaio commented 6 years ago

Most likely I am just too much of a junior dev and don't properly understand whats behind hyperHTML but I have found the Following issue while building a real world application. This is probably not related to hyperHTML but due to my poor javascript coding, but maybe somebody can point me into the right direction.

My UI gets very unresponsive, slow and slaggy when using hyperHTML.wire() to render a lot of DOM nodes. A lot isn't really that much, its basically a list with a 100 items that each has ~10 or so subnodes like in this codepen. But it seems that nodes created by hyperHTML are not properly garbage collected and I end up with tens of thousands of nodes even when they are no longer needed.

Unfortunately I wasn't able to replicate the problem within the fairly basic codepen. If I change the for loop to a 1000 I do end up with a lot of nodes (~40.000 as well) but the JS Heap Graph looks entirely different and it keeps pretty performant after the inital rendering is done.

Codepen JS Heap and Nodes image

After following the Chrome Fix Memory Problems Guide I noticed that in both my App as well as in the Codepen I end up with a lot of detached DOM nodes without being able to say where they are coming from: image

I think this might be naturally to hyperHTML but I am not a hundred percent sure if this should happen.

If I check my App with the performance profiler I see that at some point I end up with a similar amount of nodes than in the codepen with a 1000 iterations, but a lot more JS heap. image

The only way I found to resolve the problem is to display only 10 list items instead of a hundred, but this doesn't seem right as the codepen alone is performant even with a 100 list items. So there is probably somewhere in my code a pretty big memory leak but I am not able to tell where. I have tried a lot but can't find the cause of the problem. Please note that I am using wire with references but this doesn't seem to be causing or resolving the issue.

WebReflection commented 6 years ago

do you have 3rd parts scripts around ? ... like, jQuery scripts ?

WebReflection commented 6 years ago

also please check this out: https://codepen.io/WebReflection/pen/eKvLKE?editors=0010

basically what you are doing wrong, is creating each time thousands items then relating these items to nodes, but these are always new items, so you will always create new nodes.

With my codepen you can see that I relate items through an id, and a single entry point which is your app. Indirectly, instead of using wires everywhere, you could on the constructor do something like this.wire = uid => hyperHTML.wire(this, ':' + uid); and use this.wire(`list-${index}`) whenever you want/need.

jaschaio commented 6 years ago

You were right (of course). Thanks so much, I can't believe that you actually found the culprit that fast only with my vague description.

I was referencing the newly created item in a lot of places instead of using this for my wires. I changed all wires to referencing this plus making sure to use a unique id and now everything works smoothly.

Lots of virtual love 😂