Skip to content

Memory leak in state change #1096

Closed
Closed

Description

@perrygovier

It appears that changing state increases memory usage with every transition. Here's a simple example. Open your browser's memory profiler and click "Get Clicky".

http://codepen.io/perrygovier/pen/FJgBa

Pages with more stuff on it tend to increase the amount of memory that gets eaten with each transition. Note the number of nodes and listeners never decreases.

screen shot 2014-04-09 at 5 31 45 pm

On my app that uses a few larger lists, the app can quickly get to 200mb after just a few mins of manual clicking back and forth. I have yet to crash the app due to memory pressure, but it seems more a matter of impatience than something that wouldn't happen with continued use.

I believe this is less an issue with Ionic and more to do with Angular's UI Router, but I thought I'd start here as it's where it popped up for me.

BountySource discussion that appears related

Activity

  1. adamdbradley commented on Apr 10, 2014

    @adamdbradley
    Contributor
  2. perrygovier commented on Apr 11, 2014

    @perrygovier
    CollaboratorAuthor

    There's a parallel discussion that lead to this ticket being opened. It appears other users are seeing what I am in where larger apps escalate quicker.

    http://forum.ionicframework.com/t/memory-leak/2823/4

    More interesting, Aritzg created an example in pure Angular, and while memory spiked, it was quickly garbage collected. I'll try to whip up a demo this weekend to confirm. Perhaps there's something Ionic's doing to prevent or limit that GC event?

  3. perrygovier commented on Apr 13, 2014

    @perrygovier
    CollaboratorAuthor

    I've done a bit more digging, but it's still a mystery what the root cause of the issue is. I ran some benchmarks against a plain UI Router example, matching the version Ionic is using. It does appear that the leak in ng-animate has been fixed.

    This is code I used for these tests https://dl.dropboxusercontent.com/u/9006564/test.zip

    First, without ng-animate
    screen shot 2014-04-13 at 11 31 29 am

    Then, with ng-animate
    screen shot 2014-04-13 at 11 33 41 am

    Note the immediate drop in memory after each page transition using ng-animate, that's to be expected. Both are reduced back to near their original size once the CG button is clicked at the end. The stepping in the first one was automatic GC before I was able to click the button.

    It has been suggested on the UI Router github tickets, that the node and listener count perpetually increasing is actually a bug in web inspector, and can be ignored. Unfortunately, Safari and Firefox's inspector do not offer node or listener count to confirm this.

    So UI Router may not be the sole cause of the leak. Taking a closer look at Ionic:

    Here's a heap comparison (delta) going from the main page to another and back on the above UI Router demo, and the Ionic tabs demo.

    Angular UI Router example
    screen shot 2014-04-13 at 1 19 49 pm
    Here's the Ionic tabs demo
    screen shot 2014-04-13 at 1 21 43 pm

    These lists can be pretty intimidating to sift through. Worth noting however, is that the node list has a zero delta in plain UI Router, and has grown by 2240 elements in Ionic. Now, after the first dashboard -> friends -> dashboard cycle, this could be just caching. However, this is after the third cycle, so I think the node delta should be 0.

    More interesting are the elements in the Detached DOM Tree arrays. In it, I find markup from the previous pages. These detached DOM tree elements explain why having larger pages, large graphics, or video exacerbate the leak. I believe this is the primary culprit for the memory leaks that have gotten to be in the hundreds of MBs.

    screen shot 2014-04-13 at 2 47 55 pm

    Upon selecting any element in this list, I believe things that show up in yellow in the window below, indicate a reference keeping them from being released. Many of these reference createEventHandler() of the jQLight library. As plain Angular uses this too, I'll have to think about next steps in tracking this down. Maybe set up a log for that method, and then cross reference the elements with the list of elements not being released.

    The search continues.

    Hope this was helpful.

    TLDR:
    It looks like UI Router has fixed most of its problems, and the others are the inspector's fault. It appears that some event listeners aren't removed on state changes, keeping those old elements in memory even after they're removed from the DOM.

  4. adamdbradley commented on Apr 14, 2014

    @adamdbradley
    Contributor

    This is great, thanks for digging into this. So you said UI Router has fixed most of its problems, so do you mean its fixed its problems in version 0.2.7, or 0.2.10? Right now Ionic is using 0.2.7 because at the time 0.2.8 had bugs and we've been holding back and upgrading.

  5. aritzg commented on Apr 30, 2014

    @aritzg

    Hi. I have just updated to 1.0 beta.2 and replaced ui-router 0.2.7 with 0.2.10 but still the memory leak remains.

  6. ajoslin commented on Apr 30, 2014

    @ajoslin
    Contributor

    It currently is not leaking for me in Chrome 34.0.18 OSX, given the example in the OP and using ui-router 0.2.10 with the nightly build.

    Here's a codepen with 0.2.10: http://codepen.io/ionic/pen/fa145096b86fc28c81006da84028e28e/

  7. perrygovier commented on Apr 30, 2014

    @perrygovier
    CollaboratorAuthor

    Still seeing a number of detached DOM trees, but only a single stray event listener, and the memory impact after initial caching and GC is negligible. Might be a good idea to test with more complicated templates, but it's looking good to me.

  8. ajoslin commented on Apr 30, 2014

    @ajoslin
    Contributor

    We should definitely get those stray event listeners then!

    How can you tell with more clarity what is leaking? I don't really know how to use the memory profiler besides to look at the graph.

  9. aritzg commented on Apr 30, 2014

    @aritzg

    I will try to reproduce my case in CodePen. Until now, the bigger the dom objects were (say images, item lists with images), the bigger the memory leak was.

  10. perrygovier commented on Apr 30, 2014

    @perrygovier
    CollaboratorAuthor

    I don't understand it completely either, but in profiles, you can take multiple heap snapshots and then change from the summary view to the comparison view, seeing the changes in memory between two points. As you dig down, I'm not sure how to interpret everything, but I know detached DOM trees are DOM elements that are no longer in the DOM but are either waiting for GC or are being held on to by stray listeners or something similar.

    After clicking through each page and populating the cache, it's my understanding there shouldn't be any additional detached DOM trees. Still, this is substantially less of a problem than it was.

  11. aritzg commented on Apr 30, 2014

    @aritzg

    I have just forked @ajoslin 's pen

    http://codepen.io/aritzg/pen/beaFy

    As you will notice, I added a fourth tab called 'list' which shows a 6 item list. each item has a name, a description and an image.

    I you try the "get clicky" button and start a record (In Chrome ) Developer tools -> Timeline --> Memory , you will see used memory will grow. From time to time, GC will do its job but memory baseline will keep growing.

    Regards!

  12. 77 remaining items

  13. cenobyte321 commented on Apr 5, 2016

    @cenobyte321

    I've been struggling for some time now with this nasty issue. My app has a view with a PDF, rendered with PDF.js and a couple of videos, rendered with the video tag. In iOS the memory is leaking a lot when going back and forth from this view. After doing this a couple of times the app crashes. I haven't been able to pinpoint exactly where the leak is. If anyone is kind enough to lead me into the right direction for solving this, I would greatly appreciate it.

    Here's the project with only the problematic view: https://github.com/cenobyte321/ionic-pdf-video-memory

    And a screenshot showing the leak in iOS moments before crashing:

    screen shot 2016-04-05 at 3 26 35 pm

  14. reopened this on Apr 5, 2016
  15. Iodine- commented on Apr 5, 2016

    @Iodine-

    @cenobyte321 I believe i've tracked down your leak to somewhere in the PDF module you are using. When I benchmark the app without the PDF module the garbage collector can cleanup almost everything. With the module included it doesn't even get 40%. Notice how at the end of the second test the memory usage appears to return to where it was on the first transition, that's what you want to see.

    With PDF Module
    screen shot 2016-04-05 at 3 24 59 pm

    Without PDF Module
    screen shot 2016-04-05 at 3 23 43 pm

    Hope that helps.

  16. cenobyte321 commented on Apr 6, 2016

    @cenobyte321

    @Iodine- Thank you for your reply! Deleting the PDF module did reduce the memory leak, but I believe there's something else going on. By using the script I posted in the repository's readme file the memory leaked to a lesser degree, but after about 400 iterations of the script the app crashed. I know that might be an exaggeration but I could see the app still consuming memory and not releasing it, as shown in the XCode Debugger. The code I used is in the branch 'test-1-no-pdf': https://github.com/cenobyte321/ionic-pdf-video-memory/tree/test-1-no-pdf

    Here's the iOS memory graph before the crash:
    screen shot 2016-04-05 at 7 33 21 pm

    EDIT: Just as an additional sanity check I removed the $timeout calls in the view's controller and manually tested the app, it still doesn't free up memory:

    screen shot 2016-04-05 at 8 13 56 pm

  17. jrianto commented on Apr 13, 2016

    @jrianto

    My application is a simple pages with LOTS of videos on it. Navigating back and forth crashes the app eventually, before it crashes the app, it will stop loading the videos first.

    Can you check on my code and let me know how to destroy everything that is not in the current page from memory? I am new to Ionic, and not sure how to destroy/clean everything from the memory except the current page that is being viewed.

    Please check my source at http://flei.ca/FLEI33.zip

    If you load it on Google Dev Tools with ionic serve, then navigate back and forth, you will see the video will stop loading eventually. On an actual iPhone after installing the IPA to it, the apps crashes after a while and closes out.

    Thank you very much for your help!

  18. tslater commented on May 26, 2016

    @tslater

    @jgw96, is there a fix for this, or should we reference another issue, or are you thinking these are all different problems rather than an ionic bug?

  19. jgw96 commented on May 26, 2016

    @jgw96
    Contributor

    Hello @tslater ! Thanks for the questions. So, I have done alot of testing on the issues discussed here and in every case it seemed to be related to memory leaks in external libraries/external code. I could not find a good case of a memory leak that seemed to be coming from ionic. Now, this is not me saying that Ionic is written perfectly memory safe, im not sure there is a piece of software out there that is perfectly memory safe, but it does not seem that Ionic is causing the above mentioned major memory leaks or even minor ones. Also, just to be thorough i have tested on older/low-end devices (Nexus 7 2013 and Iphone 5), mid range devices(Moto X 2014) and newer, very performant devices (Nexus 6). Hope this answers your question ! Thansk for using Ionic!

  20. sdhull commented on May 26, 2016

    @sdhull

    @jgw96 wow that's very interesting. Did you see my comment from January? Have you tried out the repo I linked to there? Very vanilla implementation and easily reproducible memory problems. Right?

  21. kby799 commented on Aug 4, 2016

    @kby799

    I have this issue for awhile now, but I thought it was the way I coded so I tried to change my data structure. Still the problem persists, but I notice the problem comes only when I try to go from one view to the next. Also how inconsistent it is, sometimes it is a short climb and some other time it is a big jump that it freezes up the app.

    P.S I use tabs template to create this app, and without any manipulation from me. It also shows some kind of memory issue as well, happens between stages.

    screen shot 2016-08-04 at 15 57 03

  22. vahidvdn commented on Feb 12, 2017

    @vahidvdn

    Is there any fix? I have still the same problem.

  23. jrianto commented on Feb 12, 2017

    @jrianto

    @vahidvdn on my case, it is a coding issue as I am very new to ionic. I had to unload the audio/video from memory before loading a new one. So every time my app loads a new video/audio, I am unloading the previously loaded one by doing:
    videoElement.src =""; // empty source

    That did the trick for my app and it never crashed again. So it's not an ionic issue, it's just me not knowing how to code it properly. Hope that helps.

  24. ionitron-bot commented on Sep 4, 2018

    @ionitron-bot

    Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

  25. locked and limited conversation to collaborators on Sep 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions