WebReflection / uhtml

A micro HTML/SVG render

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

having retainers (possible memoryleak) when rendering multiple root elements

fopsdev opened this issue · comments

Hi there

I'm trying out uhtml and i've ran into a specific issue (retainers) when rendering multiple root elements like:
html`<div>1</div><div>2</div>
it doesn't happen when using an enclosed parent like:
html`<div><div>1</div><div>2</div></div>

repro here:

https://github.com/fopsdev/retainers_in_uhtml_rendering

(i've also included a mp4 showing how i go after retainers)

Thanks for any enlightment :)

I am not sure I am following your concerns or issue at all .. this library is the one that has been tested in this benchmark suit and it uses all modern Chromium driven tools, included lighthouse, to verify there are no leaks and no memory consumption. This library uses the least amount of RAM but its cache is inevitably related to the existence of template literals, unique per realm and usually persistent, and fragments are frames cached once to clone future nodes later on.

In few words, when you'll have a real-world issue I'd be happy to investigate more, right now I can tell you in 5+ years of development with this pattern (before lit-html existed) memory leaks have never been part of these libraries (hyperHTML, lighterhtml, uhtml).

Happy to dig more if you can explain in words what is it that you are after ... so far I don't have time for this as I've spent ton of time already to be sure nobody should do these checks in the wild.

Hi again
Just would like to know why there are those retainers. I'm no expert at all and i gladly believe you that this lib is well tested.
A little bit more background:
My real world issue happens in my full blown framework which i created around lit-html version 1.x
Now after updating to most recent lit-html i can see the handlers and memory doesn't get freed after garbage collection
So i took my time to create a small project which reproduces this behaviour not using my full blown opinionated framework.
And i took my time to look left and right for alternatives for lit-html and thats how i found your project and i was curious to see if uhtml has similar issues with my repro project.
If you watch the movie you could see that there are retainers originating from my small repro project.
Would appreciate if you could have a look at this issue and just give me a pointer.

oddly enough, the latest push to that benchmark uses a later patched version of uhtml where there were too many retainers, so that the heap there is not right, you should check 3.0.1 o higher ... that being said, both my libraries and lit use WeakMap to map a template literal to a DOM fragment that is used, "hydrated", and updated every time it's needed, one to many times.

In my libraries case, there's also the possibility to pass <div /><div /> as two independent divs, but that inevitably requires a virtual static fragment around those divs, to be able to move, target, append, update, these divs when needed.

Such fragment can't be freed if you clean the document because is in charge of orchestrating those divs, so until you have a reference to the template literal that renders those divs and the differ is able to move, or re-append, those divs in the future, the fragment can't just forget about those nodes, and it keeps these related.

However, once the fragment and its partial content it delivers is not referenced anymore and properly diffed, so that it cannot be moved around in the future, this can be freed and with it its nodes.

If you use keyed elements the retain is also related to the reference you used for that key, otherwise you should not be worried about fragments in uhtml or any of my libraries .. they do what they are meant to do, and the benchmark I've mentioned use these for the 5 <TD> of each <TR> of the table and it's not an issue at all, as every new run tests retained nodes and there are none.

I hope this helps or answers some of your questions.

hey thanks a lot for your pointers. it clicked now that you explained it. my takeaway will be that if i switch my framework to uhtml i'll make sure to not use independent divs just to be sure there are no retainers

and my other takeout is that you should never test for retainers using an <input type="password"/>
because: https://bugs.chromium.org/p/chromium/issues/detail?id=967438
that one fooled me for quite a few days... maybe it helps you as well

that's unfortunate though ... as you shouldn't care, because you should never have real-world issues with retainers ... I am sorry you had issues with lit-html, but without seeing your code, I don't even feel like blaming lit for it ... maybe your keyed elements were trapped somewhere else, maybe it was something else ... I hope uhtml helps you there, but maybe you should provide a more convoluted example than something so simple to explain

let's see. will start porting one of the projects tomorrow so i can compare.

The problem is that both PasswordAutofillAgent and AutofillAgent keep forms and input elements references.

yup, the problem is similar here with "static fragments" when these are referenced, even if the content they hook doesn't exist anymore ... but again, once you have these de-referenced, nothing like that bug should happen.