My application has memory issues where after a certain threshold, the application will crash.
I've been instructed to use Instruments and select the Allocation option.
However, I can never seem to get a "direct" answer to my issue, I have attached screenshots below to help describe the issue better.
The memory issues are not linked to any ViewControllers or files that I have created. Rather other libraries/frameworks which I had no idea were being used. I have been battling this issue for a few weeks, I have altered my code/implemented a variety of methods which I believed may have resolved the issue. However, no luck.
Could someone please tell me how I can combat this issue? As I cannot seem to force the memory to be released which in turn means I have this giant memory bug within my application.
Thank you.
Edit - Added a screenshot of the memory usage when viewing an image at full resolution and returning to the home screen.
A couple of thoughts:
See this answer which talks about using “Debug Memory Graph” tool featured in WWDC 2016 video Visual Debugging with Xcode. That tool is often easier to find issues than Instruments. It organizes the reference counting types by target/framework, making it much easier to sift through the results.
But if you’re dealing with non-reference counted malloced data, then Instruments is the way to go, with all the complexity that entails. But “Debug Memory Graph” is often a better first line of defense.
You said:
The memory issues are not linked to any ViewControllers or files that I have created.
Make absolutely sure that your classes aren’t any buried down there lower in the list. There will be far fewer and the sizes are smaller, so they won’t appear up at the top and they’ll be buried in the list even tho they’re likely to be the root of the problem. Frankly, if your app is running, some of your classes have to be in there somewhere. Lol.
Again, the “Debug Memory Graph” approach helps identify your own objects much more easily than Instruments.
If possible, I’d suggest running the app, returning back to some home screen where you expect stuff to have been released, and repeat that process a few times. The first time you return to a quiescent state is not very illuminating, because there’s going to be a lot of internal caching going on. But the subsequent times you exercise the app and return to that home screen, you’ll have a better example of what’s getting allocated and not released without all of this noise of stuff the OS did on the first iteration:
(Taken from WWDC 2013 Fixing Memory Issues.)
Hopefully, the “warmup” memory isn’t too dramatic, but the red area is what we often focus on, as this is what is “wasted” as we continue to use the app (resulting in eventual crashes).
Unfortunately, your allocations curve isn’t showing it drop at all, which is worrying. Now, maybe you don’t have a “home screen” to which you can return, so maybe this isn’t relevant. But even in that scenario, you should have some state in your app that you can see memory being recovered. It’s hard to say on the basis of the information provided.
You haven’t mentioned it, but confirm what debugging options you have. For example, if you have zombies turned on, you might not see memory drop back as much as it should. Often when we first encounter these sorts of issues, we start flipping on all of these debugging options, but they have an impact on the memory profile of the app. So if you’ve been turning on things like zombies or what have you, you might want to make sure you turn them back off to make sure they’re not part of the behavior you’re seeing.
I’d suggest simulating memory warnings and see if you can see memory being recovered. Make sure your code is observing and responding to memory warnings, purging memory where it can.
This is all general advice and we can’t offer specific counsel without seeing what your code is doing. I’d suggest you create a copy of your project, prune out unrelated stuff, and keep doing that until you have the smallest possible reproducible example of this unbridled memory growth. Often that process will be enough for you to diagnose the problem on your own. But we can’t pour through tons of code. We need a minimal, complete, and verifiable example of the issue.
Bottom line, “Debug Memory Graph” is often our first level of analysis. Run the app, identify what objects you expected to be released but weren’t, and go from there. Also keep an eye on how many of these objects are out there (e.g. if you see the same view controller multiple times, that’s a sign of a strong reference cycle or some circular invocation of view controllers).
Instrument just shows you overview of how your app handling memory/CPU etc. When you find something in instrument, you have to make changes in code.
Refer this: For that you should understand how stong and weak works in iOS.
Once you understand ARC in iOS. You will understand your memory leaks in your code.
Trick is :
Try to check number of objects are not getting removed from memory in instrument.
Then check code for strong reference of object and try to remove unnecessary strong references.
Hope this will help you.
I fixed the issues which I had. Just in case anyone in future experiences the same issues this is what I did:
If declared my outlets/delegates as weak
Wherever I used the keyword self in a block where XCode demanded I use self, I added either [weak self] in or [unowned self] in
Remove any instances of the word self which were not required
Added a deinit and included a print statement
Added a breakpoint where the deinit method is called
Commented out functions in my viewDidLoad method and go through each one to see which one/if one caused the issue.
Related
I'm developing an application using Xamarin.iOS. It is common knowledge, that its memory is handled very inefficiently and leaks are almost inevitable. That's why I'm trying to be as careful as possible and not to do anything stupid: no circular dependencies, no event listeners left unremoved, etc. I'm using Instruments to monitor resources used by my app. I have a following app design:
There is a UIViewControllerA which has a UITableView and a couple of labels/buttons. When you press on any of three table entries, you're navigated to UIViewControllerB, UIViewControllerC, UIViewControllerD respectively. It also makes a couple of HTTP requests. Each of the controllers also have labels, graphics, tables, scrollviews, buttons etc, and they also make HTTP requests. I'm testing my app by going from UIViewControllerA to those three and back, randomly. Meanwhile, I can see Real Memory column of Instrument's Resource Monitor increase by 1-2MB with every new appearance of new UIViewControllers. It never goes down. Since I don't really know, how memory should behave and since there is virtually no information on that topic, I don't know if this is considered to be a normal behavior for an iOS app. Is it okay? I do realize that my question is very vague, but I need to know if I need to pay attention to those "signs".
Without deeper knowledge of your code and what exactly it is doing, I would say it is not a normal behavior. If you switch between ControllerA, B and back to A it should also free up some memory. A good memory usage should look like a sawblade with up and downs.
The general problem is that the GC may not free up the memory immediately. If you have memory-heavy operations like image-processing you could consider to make use of GC.Collect() - but that should be your last option - to force a collection and free up some memory.
In addition to Instruments, which I also use heavily to profile my apps, is the Xamarin Profiler to gain more insights of what is still alive and keeps some references. If for some reason you can not use Xamarin Profiler use the build in tool called Heap Shot.
I've tried to read almost every decent tutorial in the internet, but still can't understand what is really happening here:
I've "Hide System Libraries" and "Invert the call tree", but I do not understand how to find actual code responsible for for example this leak. Any tips are appreciated. May be I am missing something obvious. I am getting hundreds of leaks, however I am using weak in closures, I do not have classes referencing each other etc. But it looks like I am missing something fundamental.
The problem shown in your screenshot is Instruments can't find your app's debug symbols. Instruments is showing memory addresses instead of function names. You are not going to be able to find the source of your memory leaks in Instruments without function names, even if you invert the call tree and hide system libraries.
Make sure your project is generating debug symbols. Check that the Generate Debug Symbols build setting is set to Yes. If your project is generating debug symbols, Instruments may be unable to find the dSYM file that contains the debug symbols. In Instruments choose Instrument > Call Tree > Locate dSYM. The dSYM is usually in the same directory as the release version's application bundle. The following article has additional information:
Instruments: Locating dSYM Files
Memory leaks can be difficult to track down. This is likely going to be a time consuming process, so be prepared. In the end, there is usually a lot of trial and error with debugging memory leaks. The "Memory Leaks" instrument has actually only detected one leak for me in the past. I've always had to track them down myself using the "Allocations" instrument.
One of the things that has helped me in the past is to start by trying to figure out what objects are actually being leaked. Click on the allocations instrument (the row above "Leak Checks"). Now try sorting by number of objects released or amount of memory used. See if there are any objects that have a count of 0 released when they shouldn't be sticking around. See if there is an object type that is taking an abnormal amount of memory.
Memory leaks are always due to developer mistakes with memory management. There are some minor memory leaks that exist in some of the lower level private APIs in Foundation and UIKit. At those lower levels, they are dealing with a lot more manual memory management, so its much easier to make tiny mistakes. You can't really do anything about those, but they are relatively rare.
If your application is working just fine, you may not need to worry about fixing these. There is some cost benefit analysis you want to do here. If this isn't impacting performance or stability, is the time investment in fixing these right now worth the minor benefits it will provide you and your users?
However it is worth nothing that memory leaks can add up, so if a user has your app open for a long time, the amount of leaked memory will eventually become a problem if you continue to leak more objects over time. At some point the application will crash and the user will have to re-open. But if your memory leaks are small enough that this doesn't become an issue unless the app has been open for HOURS, is it really that much of a problem anyways? That's always a judgment call on your part.
It's the first time I have to fix a memory problem from one of my iOS apps, so I'm not really sure how to track it, I've been reading some post from different blogs and I've found that my memory is constantly increasing:
The problem is that I don't know how to track and fix the problems in my code, and I also don't know what should be the best "Growth" in memory. Thank you.
First, I'd recommend watching WWDC 2013 Fixing Memory Problems and WWDC 2012 iOS App Performance: Memory videos. They are dated, yet still relevant, demonstrating of taking the above screen snapshot down to the next level in order to identify the underlying source of the memory issue.
That having been said, I have a couple of observations:
In my experience, nowadays, the problem is rarely "leaked memory" (i.e. memory that has been allocated, for which there are no more references, but you neglected to free it). It's rather hard to leak in Swift (and if you use the static analyzer on Objective-C code, the same it true there, too).
The more common problem is "abandoned memory" resulting from strong reference cycles, repeating timers not getting invalidated, circular references between view controller scenes, etc. These won't be identified by the Leaks tool. Only by digging into the Allocations tool.
First, I often like to see what accounts for the bulk of the abandoned memory. So I double click on a top level call tree and it will show me where the abandoned memory was allocated:
Note, this doesn't tell me why this was abandoned, but by knowing where the bulk of the abandoned memory was allocated, it gives me some clues (in this example, I'm starting to suspect the SecondViewController).
I then drill into the generations results and start by looking for my classes in the allocations (you can also do this by manually selecting a relevant portion of the allocations graph, as discussed here). I then filter the results, searching for my classes here. Sure, this won't always be the most significant allocation, but in my experience this sort of abandoned memory almost always stems from some misuse of my classes:
Again, this is pointing me to that SecondViewController class.
Note, when looking at generations, I generally ignore the first one or two generations because they may have false positives stemming from the app "warming up". I focus on the latter generations (and make sure that I only "mark" a generation when the app has been returned to some-steady, quiescent state.
For the sake of completion, it's worth pointing out that it's sometimes useful running Instruments with the "Record reference counts" feature on the unreleased allocation:
If you do that, you can sometimes drill into the list of retain and release calls and identify who still has the strong reference (focus on unpaired retain/release calls). In this case it's not very useful because there are just too many, but I mention in because sometimes this is useful to diagnose who still has the strong reference:
If you're using Xcode 8, it has a brilliant object graph debugger that cuts through much of this, graphically representing the strong references to the object in question, for example:
From this, the problem jumps out at me, that I not only have the navigation controller maintaining a reference to this view controller, but a timer. This happens to be a repeating timer for which I neglected to invalidate. In this case, that's why this object is not getting deallocated.
In the absence of Xcode 8's object graph debugger, you're left to pouring through the retain and release references (and you can look at where each of those strong references were established and determine if they were properly released) or just looking through my code for things that might be retaining that particular view controller (strong reference cycles, repeating timers, and circular view controller references are the most common problems I see).
Minimizing your app's Memory Footprint
For the benefit of both stability and performance, it's important to understand and heed the differing amounts of memory that are available to your app across the various devices your app supports. Minimizing the memory usage of your app is the best way to ensure it runs at full speed and avoids crashing due to memory depletion in customer instantiations. Furthermore, using the Allocations Instrument to assess large memory allocations within your app can sometimes be a quick exercise that can yield surprising performance gains.
Apple Official Document
I've kind of a weird issue with my iOS app.
after a while my app goes low in memory so memory warning, everything seems to be fine, but when I check the memory usage I noticed that all the calls to viewDidUnload didn't free up lot of memory, so after a few click in my app, it goes again in memory warning, everything seems to be fine again, but not a lot a memory have been released, so it goes again in memory warning faster, and then it crash (after the third memory warning most of the time). this crash is random : app freeze, app leaves, my debugger says app paused, but no bad access or sigbort, no zombies.
my guess is that memory warning can't free up enough memory has it should.
(I checked all my viewDidUnload and make nil every objects that are allocated in viewDidLoad)
Any help will be usefull !
thanks a lot.
So I managed to work with my issue.
I wrote "-(void) dealloc" methode in all my controllers and check if I enter in it as I should. (on pop controller, dissmiss etc..)
Every time it didn't, I do step by step in the controller to see what was retaining my controller from beeing dealloc.
most of the time it was some property that was not in "unsafe_unretained"
delegate that was in "ASSIGN" (and should not be in assign but in unsafe_unretained)
(heritage from non-ARC project...)
I also had some strange controller with XIB that was not deallocated even if empty.
I rebuild new one step by step with copy/paste and finaly with exactly the same code, the new controller was released, with no visible difference between then !!! gnneee
at least I know how to debug that kind issues now...
I don't think there's any way to give a specific answer without more data so the best I can do is suggest that you stop guessing what might be happening with your app and learn how to measure what is actually going on. Run your app under Instruments and you'll be able to check for leaks and also actually see what classes are responsible for the most of your application's memory footprint.
You should make sure you know how to use both the Leaks instrument to identify leaked object but also the Allocations instrument to identify orphaned (but not leaked) sets of objects which should have been released or just cases where your app is not responding to memory warnings as you expected.
https://developer.apple.com/library/ios/#documentation/developertools/conceptual/InstrumentsUserGuide/AboutTracing/AboutTracing.html might be a good place to start and there are a number of tutorials available as well; http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial and http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/ are among the first results I saw.
Vassily,
First, if you aren't yourself releasing extra memory, the the -didReceiveMemory warning does you no good and the OS will keep asking for memory until you are killed. This sounds like it is your problem.
Second, if that isn't the problem then you are probably getting terminated due to the size of your resident memory partitions. Make sure you look at your VM allocation in Instruments. I expect the MALLOC_TINY or MALLOC_SMALL both have greater than 5 MB resident and dirty footprints. Due to the nature of small allocations these VM regions will never shrink. The only option you really have is to not create a lot of small items in the first place. This is really only something you can address by changing you code's algorithms to use less memory.
Andrew
I'm writing a game using Corona for a game design class and though I'm still learning, I've got most of the basics down. Right now, I have a situation where the program slows down after about two minutes or so of playing, and I'm not entirely sure why. I've already implemented code to remove all bodies which have served their purpose and I even have it set up to print a notification when each one is removed.
http://www.mediafire.com/?5fz7ru0c6euwq1k
This is the download link. Any help is greatly appreciated. Thanks!
First off, have you checked the memory usage? If the problem gradually slows down that certainly sounds like a memory leak, but you need to check the memory usage to be sure. Print out memory usage to the console like so:
print("mem "..collectgarbage("count"))
Put that in an enterFrame listener so that you can watch the memory usage continuously while your app is running.
Now once you are seeing the memory consumed by your app, the most crucial step in any sort of debugging is isolating the problem. That is, zero in on the spot in the code that causes the problem. For some problems you can rely on techniques like printing debug messages to the console, but for a memory leak your best bet is often to selectively comment out sections of the code to see what affect that has on memory.
For example, first comment out the event listeners on one screen and then check the memory usage. If the leak is gone, then you know the problem was something to do with those event listeners. If the leak is unaffected, then restore those event listeners and comment out the next possible cause of a memory leak. rinse and repeat
Once you know the exact section of code that is causing the leak, you will probably be able to see what you need to fix. If not, ask about that specific code.