I need to load 5MB of HD images (for iPad) before my game starts up. It crashes somewhere in the loading progress. Well, to confirm it was the 5MB problem, I then tried to load 2.5MB of LD images (iPhone quality) instead. It ran OK, no crashes.
Does it mean that I can't reserve 5MB or more memory? There should be a way to do it.
This happens more frequently when more apps pending in the background. And it doesn't crash if I run my game immediately after a clean reboot. Therefore, it must be a memory problem crashing my game.
Any idea how I can handle this?
5MB of compressed image data can easily explose to many (4x-10x) the memory requirements to have them uncompressed.
Any idea how I can handle this?
Use Apple's Instruments and look at memory usage.
Next ensure iOS itself is not caching images (look at the API you're using and their documentation, some will cache, others won't).
Then look if you can dispose of the image earlier. Images can be quite big (and a lot of memory for them is internal to iOS, which is why using Instruments will give you a better picture than MonoTouch's own HeapShot profiler) so disposing it manually (instead of waiting for the GC is generally a good idea).
Also look if you can delay load some images (or at least their decompressed versions), e.g. after the first one(s) are disposed.
Related
I'm working with an app that utalizes a lot of local images i.e. images that have source like require(../assets/MyImage.png).
During development I didn't face any issues, however when I built my app for release on iphone 5s, I started getting random device restarts. After some research I found out that whenever I was browsing through my app and loading all these various images (some of them are heavy background images) they were persisted in iOS memory / RAM.
Memory was not cleared after I unmounted screens / navigated to different screens, it just kept growing while I was using my app and loading new images and eventually app crashed.
I found that there is an AppDelegate method in iOS called didReceiveMemoryWarning that can be used to perform cache clearing when app is using too much memory, but I can't figure out what cache and how I should clear to remove react-native images in iOS?
Would appreciate any advice on the topic.
NOTE: I've read somewhere that iOS will auto manage memory, but after using XCode memory profiler and Instruments, I don't believe this is happening, it just keeps growing upwards whenever new resource is mounted on the screen.
Memory profiler output
After various attempts to find a solution I ended up using following image package https://github.com/DylanVann/react-native-fast-image
It improved memory management and performance of my images. As additional benefit it allows to use WebP images in iOS project which reduced my bundle size substantially.
I'm trying to debug why our SceneKit-based app is using so much memory but Xcode and Instruments / Allocations seem to have very different values for the amount of memory being used. When I look in Xcode I see something like 600 MB but when I transfer the same running session over to Instruments / Allocations, I see a very different number for persistent bytes, like 150 MB.
Which one is correct? Why the difference? Are they measuring different things?
(Regardless of whether I Transfer an Xcode debug session or start fresh in Instruments, it doesn't seem to make much difference.)
The reason that I care is that iOS is killing the app for excessive memory use (according to Xcode) but I can't seem to find the problem via Instruments.
I've tried turning off all GPU and Metal debug options but they don't seem to make a difference.
Which one is correct?
My intuition is: Instruments. It uses Dtrace to (sorry) instrument your code and watch actual allocations and deallocations as they happen, at the expense of performance. The Xcode debug navigator memory graph is more of an outside view designed to give a very general sense of what’s happening. That is exactly why the latter offers you a way to switch to the former — because that (Instruments) is where you’re going to get real measurements.
(However, let’s keep in mind that Instruments may fail to include in the total you’re seeing some virtual memory backing stores for graphics. There are plenty of WWDC videos discussing this topic in more detail. )
I know that this answer is quite late, but for the sake of future developers with the same problem, I would advise you to check the images in your assets folder. If any of your images have dimensions larger than 1000 x 1000 you should scale them down. With the example above, the image comprises of 1000000 pixels. Following how images are loading in (4 bytes per pixel), this means 4 MB of memory is used to load the image. Unbeknownst to me, I had an image of roughly 3600 * 4000 in my assets folder. Doing the maths, this was over 50 MB of memory usage!
I've been struggling to find out why my application continues to increase in memory as I move throughout the application.
When leaving the view, I make sure to check to see if the controller is de-initialized and it is, but the memory that was added while in the view retains. I've used the instruments tool and it hasn't detected any leaks, and leaving/re-entering the view repeatedly doesn't have any effect on the used memory.
This leads me to believe that iOS by default caches the UIImage into memory, and only frees the memory if the device needs it.
The view that I'm working with is a UICollectionView which shows the user a gallery of pictures that have been uploaded to my server. Currently I have this limited at 10 images per user, but as you can imagine if there's quite a few images and that can increase the memory rather quickly.
Do I need to worry about this memory? Is it default behaviour for the images to stay in memory until the device needs to free some space? I don't want to submit to the application store and get rejected for poor memory-management.
EDIT: It's also fair to note that I am constructing the image using the UIImage(data: NSData) constructor.
iOS does natively cache plenty of memory. The underlying support for that is in libcache, which UIKit uses internally, in a way that is inaccessible to you.
During times of "memory pressure", that is, when RAM is low, an event (technically , a knote) is broadcast to all listeners. Your app is listening because the frameworks automatically open a kevent file descriptor, and react to it with the well known didReceiveLowMemoryWarning.
Remember, there's no swap in iOS (discounting compressed RAM for the scope of this answer), so this happens quite frequently.
Even before didReceiveLowMemoryWarning is passed to you, libcache uses the malloc feature of "zone pressure relief" , which you can see for yourself in :
...
/* Empty out caches in the face of memory pressure. The callback may be NULL. Present in version >=
8. */
size_t (*pressure_relief)(struct _malloc_zone_t *zone, size_t goal);
} malloc_zone_t;
Thus, images (main consumers of memory) will be purged if necessary, and therefore should be of much concern to you. That said, if you know you don't want a given UI object anymore, you can of course dispose of it explicitly. Of course, if you have any additional resources that cannot be auto-purged in this way, you should handle them in the delegate. Because if you don't, Jetsam will jettison your app (i.e. kill you with an untrappable -9), and probably slay a few innocents in your priority band as well.
In my app I am getting low memory warning after few files download.I stops current download process. Even after that also app crashes and I am assuming that app crashes due to low memory issue. Can any one please let me know how can I free up memory in running app.
It sounds like you're downloading the files straight to memory. That will be an issue because you wont have enough memory to download the entire file.
The strategy you need to take is, as you download the file continue to write chunks of it out to disk, freeing up memory in doing so.
If you are using NSURLSession there is a parameter you can use to do this for you with little effort. Please post your code for in depth help.
I have a strange memory issue I'm having problems resolving and would appreciate some advice as to where else to look.
The program I have (iPhone App) has a function whereby it basically downloads loads of files, processes those that are JSON, and stores the rest to disk. The JSON processing is CPU intensive and can take several seconds per file, so I have a NSOperationQueue with maxConcurrency limited to 1 that handles all the heavy lifting, and a queue that manages the multiple files to download.
Ever since iOS5 came out, the App has had problems completing the download sequence without crashing and so far what I have tried is;
1) Changed the performSelectorOnBackgroundThread JSON processing to use a single NSOperationQueue so as to limit the number of background threads working with large objects.
2) Added NSAutoReleasePools inside loops that create multiple, large, transient objects.
3) Flushed the sharedURLCache to ensure the files aren't hanging around in the system cache.
4) Stored the JSON objects to disk using NSKeyedArchiver and passed the filenames between threads rather than the actual objects, to again try to mitigate the number and size of retained objects currently in use.
All of these at first seemed to make a difference, and when I look at the memory allocations, I've now got the peak usage down from just over 20MB (hence no wonder it was crashing) to under 10MB, and yet the app is still crashing with low memory as before.
I'm trying to trace what is eating the memory causing the app to crash and on this occasion I'm having real problems persuading Instruments to tell me anything useful.
Here's a typical trace (on an iPhone 3GS running iOS 4.3.5)
You can see that the PEAK usage was a tad over 7MB and yet shortly after, you can see the 2 flags pertaining to low memory, and then low memory urgent, followed by the app terminating shortly thereafter.
If I use the memory monitor, the cause of the crash seems clear enough - physical memory is being exhausted - look at the light green trace below. The low memory warnings co-incide (not surprisingly) with the physical memory running out.
There are no leaks showing FWIW either (I've done that in other runs).
It's not image caches or NSURLConnection caches and the only thing I can think of is that perhaps there are some bad leaks that aren't being detected ... but I'm having issues identifying them because if I click into all allocations to see the objects that are live, and then do a command-A to select them all (in order to paste them into a spreadsheet to see where the memory seems to be), at the point I hit command-C to copy them, Instruments beachballs and never recovers.
I really cant figure out what's going on. Does anyone have some advice on how to persuade instruments to show me some more useful information about what is using this memory?
Sorry I can't post any meaningful code fragments ... hopefully the instruments screenshots at least give you an idea about where I'm coming from.
The Leaks instrument isn't terribly useful for figuring out anything but the obvious leaks in your app.
What you are describing is an ideal candidate for heapshot analysis.
tl;dr Heapshot analysis allows you to see exactly how the heap of your application grows between any two points of time (where you determine the points).