We run a production project on lit-element and have noticed that the app is becoming progressively slow to render as we add more components. This happens only if the user accesses more pages (hence more components). Given the PWA nature of polymer examples we followed, any garbage collection is probably hidden from the developer and done by lit-element itself.
One possible reason I observed is the lit-element behavior of keeping the element in an unknown place (let's call it a 'secret dungeon') even it's not in the DOM (I can confirm this as element styles are still there on next reuse).
In principle, this is good behavior as it makes the next render faster. However, in practice, copies of the same element keep getting added to this unknown place making the app slower over sustained use. To partially resolve this, I took some parts out of an if / else and instead used display:none / display: block so that multiple copies aren't saved in this 'unknown place'.
Can someone throw any light on if this is expected behavior? I am trying to put together a stackblitz example, but it isn't easy to reproduce the progressively slow behavior in production. Just a note, we use webpack, redux and fetch calls as well. I was able to verify it is an issue on render, and that redux and fetch aren't part of the problem.
What secret dungeon are you talking about?
Oh it's a metaphor. I can't find the element in the DOM / shadow-DOM (as expected), but any custom manually applied styles are retained for next use. If it's not in the DOM, the element must be stored somewhere?
I'm really not sure why an element wouldn't be in the DOM. What element(s) exactly are you talking about?
hey fellas
of course, dom nodes can be simply connected or disconnected from a document -- and disconnecting a node from a document doesn't delete it nor mark it for garbage collection or anything special -- the node is just no longer referenced by that document
so it's perfectly normal to take an element, disconnect it from the dom, hang onto it, make style changes or whatever, and later when you attach it to the dom, your changes will be "retained for next use" -- @rickygarg, is this what you mean?
for the sake of garbage collection, it's up to us to make sure our javascript programs aren't hanging onto unwanted references (that's where WeakMap comes to the rescue, right?)
so is the "secret dungeon" a suspicion that lit-element is hanging onto references to old nodes that it shouldn't be?
these days, i suspect the chrome profiling devtools could help pinpoint the cause of such issues, no? my suspicion is that the secret dungeon is most likely in your application code, probably not in lit-element.. but who knows, at least there's a way to find out :)
wherever the problem may be rooted, i suspect that a well-placed WeakMap just might solve it
馃憢 chase
Thanks Chase. Yes, I indeed meant the 'disconnected' dom elements. It'd be nice to be able to pinpoint the actual WeakMap used by lit-element so I can debug find my elements there, but JS Profiler is a great idea meanwhile :) Here are some stats:
I tried regularly browsing our app (see profiler results) and noticed that it is the render method on lit-element that takes most time. The issue is this gets progressively slower (fetch calls take the same time).
On a a particular screen, I show either a loading icon, or a list of elements. I compared the render speed using the if-else construct versus using a property on css display. When I use if-else, there is a massive difference between profiler results initially and profiler results afterwards. Does it look like it has something to do with apply-shim?
In comparison, the same screen is consistently faster if I use the css display property (see profiler results when using css display - the render script isn't at the top anymore).
Could someone with experience in lit-element suggest what I might be doing wrong? My attempts so far for a stackblitz example have been unable to reproduce the issue, but maybe someone can build on it.
Appreciate all the help.
@rickygarg Seems like you might want to reduce the number of rendered nodes on a screen.
Per our CONTRIBUTING guidelines, we'd really need a repro demonstrating a specific issue in order to assist. If you suspect a memory/object leak, please try to create a repro we can run to help track down an issue.
Note that as more paths through an application are rendered, lit will build a cache to <template>s for template results that have been parsed to prevent re-parsing if the app takes that path again. This is by design and an overhead we have not seen to cause runtime performance issues, but if you can make a repro that demonstrates such a real-world problem we can look into it.
Also note that there was a Chrome memory leak related to adoptedStylesheets that affected LitElement that was resolved in Chrome 78: https://github.com/Polymer/lit-element/issues/804.
Closing without a reproduction case. @rickygarg if you can help make a reproduction case to point us at a specific problem to investigate, please re-open a new issue. Thanks.
Most helpful comment
Thanks Chase. Yes, I indeed meant the 'disconnected' dom elements. It'd be nice to be able to pinpoint the actual WeakMap used by lit-element so I can debug find my elements there, but JS Profiler is a great idea meanwhile :) Here are some stats:
I tried regularly browsing our app (see profiler results) and noticed that it is the render method on lit-element that takes most time. The issue is this gets progressively slower (fetch calls take the same time).
On a a particular screen, I show either a loading icon, or a list of elements. I compared the render speed using the if-else construct versus using a property on css display. When I use if-else, there is a massive difference between profiler results initially and profiler results afterwards. Does it look like it has something to do with apply-shim?
In comparison, the same screen is consistently faster if I use the css display property (see profiler results when using css display - the render script isn't at the top anymore).
Could someone with experience in lit-element suggest what I might be doing wrong? My attempts so far for a stackblitz example have been unable to reproduce the issue, but maybe someone can build on it.
Appreciate all the help.