reagent

Michelle Lim 2024-05-08T19:57:33.570759Z

hi there, does anyone have experience optimizing performance or dealing with memory leaks in reagent apps?

p-himik 2024-05-08T20:09:34.849869Z

Hey. Plenty of people. Do you have some specific questions?

Michelle Lim 2024-05-08T20:12:21.221689Z

hey, thanks for the quick response. we have some pages eating up to 5GB. i've never dealt with this before, so i guess my question would be where to start looking/thinking about this. sorry it's vague, i just don't know enough to ask better questions

p-himik 2024-05-08T20:21:19.481279Z

At least Chrome has a memory profiler. In my experience, it's pretty useful for that.

Michelle Lim 2024-05-08T20:22:57.062289Z

oh i should clarify -- js heap snapshot memory is totally fine, consistently ~200MB. but the full memory footprint is so much higher (seen in the chrome task manager or hovering over the tab)

Michelle Lim 2024-05-08T20:46:46.262419Z

there seems to be a total lack of resources that concretely show how someone could go about tackling this sort of thing. maybe that's for a good reason, but it feels impenetrable

p-himik 2024-05-08T20:49:16.846189Z

Hmm, never noticed it in my apps. But reading around suggests that it's either some resources outside of JS (cached media, CSS, JS files themselves, images, etc.) or the DevTools panel if you keep it open.

p-himik 2024-05-08T20:50:35.642619Z

Do you do anything "weird"? Like constantly re-adding DOM nodes, using dynamic styles, generating images, recreating canvases, etc.

Michelle Lim 2024-05-08T21:05:42.980419Z

short answer: yes. will try to provide more detail in a bit!

Edward 2024-05-08T22:05:35.900159Z

Speaking about memory profiler we do have it but run into a log that lead to reagent -> memoize function, which was never used. What could be the reason of caching the components if that's so? operation_name leads to memoize cljs fn*

p-himik 2024-05-08T22:34:29.635199Z

A few things: • That's not Reagent, that's a partial and modified copy of Reagent from re-frame-10x. Judging by operation_name, your version is also outdated - I've removed that very function from there 2.5 years ago • That function doesn't cache components, it caches components' names. However, such caching can only rely on the components themselves, so they used to be held in memory by the caching • Reagent itself uses caching but only for components, so it doesn't recreate components every time. A reason not to create components dynamically

Edward 2024-05-09T16:35:15.702519Z

Thanks, got it. Temporarily removed 10x so it won't distract from the main things. I think about the component caching: as far as I know we don't have any especially when redirecting somewhere in the app, but the graph in the performance tab shows increasing peaks every time I switch pages from first to second and vice versa. Is there a way how to check not-used nodes or remove them manually in reagent or somehow else?

p-himik 2024-05-09T16:51:37.960989Z

I'm not aware of that. You can probably build something that walks a memory snapshot right in the JS process and compares it to what classes are cached. Or you can copy the right Reagent namespace and add monitoring to the caching. But IMO a better time investment would be to go through your code and see where you create components dynamically, and to stop doing that. You can always replace a closure with a parameterized component.

Michelle Lim 2024-05-09T16:55:03.647529Z

by dynamic components, do you mean components generated in a list by map or for?

p-himik 2024-05-09T16:57:19.027139Z

I mean functions created at run time that you then use as components. Not to be confused with form-2 or form-3 components.

Edward 2024-05-09T17:58:53.604399Z

Just wondering why closures are memory-leakable?

p-himik 2024-05-09T18:05:06.658489Z

Because the components made from them are cached.

p-himik 2024-05-09T18:05:14.369669Z

At least, that's my understanding of the situation.

p-himik 2024-05-09T18:06:25.003459Z

Actually, I'm most likely wrong - the caching is not via a global cache but rather on the function itself.

p-himik 2024-05-09T18:07:12.731309Z

Yeah, I'm wrong, closures should be fine. Must be flashbacks from that operation-name since it used a global cache.

Edward 2024-05-09T18:07:40.130399Z

Yeah, that's what I'm thinking about. We do have several closures but I don't think that's the problem

Edward 2024-05-09T18:09:25.893029Z

We also had fn memoization, but it was improved and located in a different place, so I think the caching theory is not relevant for now

Edward 2024-05-09T18:15:36.632459Z

Through the things we currently investigated is DOM nodes are not deleted after we move to a different page or switching view from one component to a different one. But how to check this theory practically I'm not sure. Your theory with dynamic components sounds interesting but I also not sure that I understand this term. Maybe you could recommend smth to read?

p-himik 2024-05-09T18:26:26.717309Z

Yeah, forget about dynamic components - they shouldn't be relevant, sorry for the noise. The above picture you've uploaded, where is it from?

Edward 2024-05-09T18:29:20.329129Z

It's from the performance tab in Chrome dev tools. I'm investigating memory leaks by these peaks. Afaik these peaks should go up and down after some time because the garbage collector will remove all unused DOM nodes, but moves only up (yeah, sometimes it comes a little down but neglectable)

p-himik 2024-05-09T18:43:04.029039Z

Huh, how exactly do you get to that view? I don't seem to have anything resembling it, neither in the Performance tab nor in the Memory tab (which, BTW, should be useful in your case).

Edward 2024-05-09T18:52:54.058319Z

I use Chrome since for debugging I like it more than everything else. Dev-tools -> performance -> record for some time -> make some actions to trigger memory leak -> stop and under request inspector there should be smth like this

Edward 2024-05-09T18:55:47.860879Z

Kinda similar thing can be achieved in the memory tab. There also we can record actions and then inspect what happened. But I can't understand the memory tab fully because I think it's working with js heap, which in my case was successfully thrown away by garbage collector (blue line on the picture above)

p-himik 2024-05-09T19:11:15.519839Z

Are you sure it's not a plugin? Because here's what I see, and there are no graphs at the bottom.

p-himik 2024-05-09T19:12:27.591449Z

Regarding the memory tab - I don't know whether it counts references to DOM nodes as a part of the heap. If it does then yeah, won't help much. But if it doesn't then it might be helpful.

Edward 2024-05-09T19:24:29.622989Z

No plugins since I'm in incognito mode. Maybe version? I have Version 118.0.5993.88 (Official Build) (arm64)

p-himik 2024-05-09T20:05:03.111129Z

124.0.6367.155 here. And I see that I'm not alone, but this question is from 2022: https://stackoverflow.com/questions/74575787/why-cant-i-see-the-js-heap-documents-nodes-listeners-gpu-memory-section-in-my-d

p-himik 2024-05-09T20:05:43.788519Z

I can get to this panel, but it's completely unrelated to the Performance tab and is continuous.

Edward 2024-05-09T20:41:54.082869Z

That's weird. I have it and it shows the leakage, I checked some tutorials and the do have this as well and they use it ti identiry leakage