1

I have two components: ComponentList and ComponentDetail. The way it works right now is that a user will choose one from the list and it would redirect it to the ComponentDetail that calls an API and gets a large data set for an observable. Now, the problem that I am encountering is that when I go back to the ComponentList, the memory that is used by the ComponentDetail is not being garbage collected upon onDestroy. It goes down after ten minutes but if forced GC'd from the devtools it would release the memory space quickly. I am not sure which is causing it to take a long time to be collected automatically, is there something I could do to make the garbage collection happen right after the ngOnDestroy?

gby
  • 121
  • 8
  • 1
    Are you unsubscribing from the API observable when your component is destroyed? See [Angular/RxJS When should I unsubscribe from `Subscription`](https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription) – D M Oct 27 '21 at 14:16
  • I came to ask the same question, in my experience, this usually means something is still subscribed – chad_ Oct 27 '21 at 14:18
  • 2
    `ngDestroy` doesn't have a responsibility for the GC. GC decides when to collect or not by it self. `ngDestory` makes the data used by component collectible. You could say something is wrong when you forcibly trigger a garbage collection and the memory consumption were still the same. But as you said it's not the case. – Eldar Oct 27 '21 at 14:19
  • "if forced GC'd from the devtools it would release the memory space quickly" - then i don't see a problem? It's not like GC keeping memory for future usage is anything weird or worrysome. – ASDFGerte Oct 27 '21 at 14:19
  • Garbage collection is handled by the JavaScript runtime. Generally, it's best to let JavaScript handle it. You can and should do what you can to influence it by making sure you've released all that can be released, but trying to force the GC to collect is a recipe for disaster. – Heretic Monkey Oct 27 '21 at 14:21
  • Thanks for the response! I just wasn't sure why it was not happening as soon as the component is destroyed. I'll check my subscriptions again just to be sure. – gby Oct 27 '21 at 14:39

1 Answers1

5

(V8 developer here.)

Just to confirm what commenters have said: there is no way to force immediate garbage collection, and you shouldn't have to worry about it. When your app makes an object eligible for garbage collection (by dropping all references to it), then the garbage collector will free it the next time it runs, which could be fairly soon, or it could take a while. The reason is simply that finding dead objects is an expensive operation, so V8 (and, of course, other JS engines just the same) is very carefully tuned to find a good balance between freeing memory reasonably quickly (especially when there is memory pressure) and not spending too much CPU time on doing so.

In the case at hand, it is unsurprising that when you allocate a single large object (or group of objects), and then drop all references to it, and then just wait, it'll take a while for the next GC cycle to kick in; whereas if you continued to allocate large objects, then all that allocation activity would be a strong hint for the GC to kick in and go looking for garbage it can free.

jmrk
  • 34,271
  • 7
  • 59
  • 74