SolvedNativeScript Memory Leak on iOS since tns-ios 3.0.0

Tell us about the problem

The image below is this app (shown on the left) going back and forth between a homepage and a page with a listview. Back-navigation doesn't clear the memory of the listview (inspecting the heap it mostly looks like retained labels, but I find it very hard to interpret):

172loops

Note this is a screenshot of the app after going back and forth exactly 172 times (as shown in the app's screenshot), and the blue graph on the right is Xcode reporting the heap size over time. As you can see it's growing with every visit of the listview.

Q. Dude, this is artificial!

A. While this may seem very artificial, I actually created this app to demonstrate a problem I saw in a real app. The app crashes after about 20 minutes of usage on an iPad Air (1GB RAM). It has lots more graphics and styling than this demo, so I had to add a lot of labels and automated navigation to reach the same level of memory pressure my app has. The problem with both apps is exactly the same: memory is retained. Forever. Until the app crashes.

Which platform(s) does your issue occur on?

iOS (didn't check Android)

Please provide the following version numbers that your issue occurs with:

  • CLI: 3.1.0
  • Cross-platform modules: 3.1.0
  • Runtime(s): tns-ios 3.0.0 and 3.1.0 (same issue)
  • Plugin(s): n/a

Please tell us how to recreate the issue in as much detail as possible.

Follow the instruction in the "Fully automated {N} Out Of Memory Crash App". It's based on this template.

I hope this app will help in identifying and verifying possible solutions. I've tried a few my own, but there are a few internal classes in the runtime I can't inspect so my hands are a bit tied in this case.

Thanks for any feedback you have in advance,
Eddy

18 Answers

✔️Accepted Answer

@ivanbuhov Tears of joy in my eyes - this seems to fix it indeed!

My test app (linked from the first comment) is an Angular app that loads an extreme amount of <Label>s in a <ListView>. Then goes back and reloads that list. 250x. The issue was (likely) the labels being retained and was also reproducable in a non-Angular app with RadListView.

To verify the fix I just ran tns-ios 3.1.0 on my iPhone 5s and 459 MB was retained after 250 loops and a call to GC(). At about 430 MB the console stared showing memory warning. Another 50-ish loops and it would have crashed the app:

screen shot 2017-08-25 at 15 17 15

Then I did this to get your fix:

tns platform remove ios
tns platform add ios@next

Next I rebooted my iPhone to make sure I had the same baseline and ran it again. Behold:

screen shot 2017-08-25 at 15 35 41

The app never peaked above 180 MB and after GC() it only retained 94 MB of memory (only a little more than when I started the app). This seems even better than my 2.5.0 testresult, but that's not the important point here ;)

THANK YOU!

Other Answers:

I found a memory leak in the iOS Runtime introduced in 3.0. This PR fixes the leak and makes the Xcode memory debugger to print no errors in a blank application.

However, some leaks are still reported in the Leak tool in instruments. After inspecting the call stack when the leaked memory is allocated, it seems that the Xcode Instruments consider the memory allocated here and here as leaked. Actually, this memory is owned by the FFICall instance and is deallocated in its destructor. However, most of the FFICall objects are never destructed (which is expected and desired behavior) and the memory is never deallocated (which is expected, too). It seems that this makes the Instruments to treat the memory as leaked, even if actually it is not.

Initially, I thought that the usage of new is what makes the Instruments tools to treat the memory as leaked, but even after refactoring the code to avoid the usage of new operator and replacing it with unique_ptr and std::vector objects saved as an instance variable (following the RAII technique), the allocations are still treated as memory leaks.

P.S.: I haven't investigated the tns-core-modules and the example app for existing memory leaks in their codebase. My main focus was the iOS Runtime.

I just tested the demo app with this tns-ios line changed to 2.5.0 and that produced a nice flat memory graph - so the issue was introduced with 3.0.0.

Here's tns-ios 2.5.0 after 100 loops and GC (tns-ios 3.0.0 and 3.1.0 consume 430 MB after GC):

screen shot 2017-07-04 at 15 18 53

Also tested tns-ios 2.5.1 which produces a similar nice flat graph. So the problem was introduced between 2.5.1 and 3.0.0.

@EddyVerbruggen just install tns platform add ios@next or use next without @ in the package.json

More Issues: