Fork me on GitHub
#reagent
<
2024-05-08
>
Michelle Lim19:05:33

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

p-himik20:05:34

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

Michelle Lim20:05:21

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-himik20:05:19

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

Michelle Lim20:05:57

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 Lim20:05:46

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-himik20:05:16

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-himik20:05:35

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

Michelle Lim21:05:42

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

Edward22:05:35

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-himik22:05:29

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

Edward16:05:15

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-himik16:05:37

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 Lim16:05:03

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

p-himik16:05:19

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

Edward17:05:53

Just wondering why closures are memory-leakable?

p-himik18:05:06

Because the components made from them are cached.

p-himik18:05:14

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

p-himik18:05:25

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

p-himik18:05:12

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

Edward18:05:40

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

Edward18:05:25

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

Edward18:05:36

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-himik18:05:26

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

Edward18:05:20

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-himik18:05:04

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).

Edward18:05:54

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

Edward18:05:47

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-himik19:05:15

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

p-himik19:05:27

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.

Edward19:05:29

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

p-himik20:05:43

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

Edward20:05:54

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