MFMailComposeViewController uses too much memory - objective-c

When I try to send images as attachements(summar size ~4mb) by using MFMailCompose, activity monitor says, what 100(+-2)mb of memory is used. After sending or cancelling memory is freeing ~20 megabytes, but what happened to the remaining 80 megabytes if shared item with images is deallocated?
Thanks!:)

An image's file size and the amount of memory it consumes when displayed are two completely different things.
Images such as JPEGs and PNGs are compressed. When they are drawn to the screen they are uncompressed.
A quick rule of thumb to figure out how much memory an image will consume when displayed is
memory consumed = (width * height) * 4
Example, a image that is 2 KB on disk, but is 62 x 52 pixels will actually consume 12,896 bytes or 12 KB. I imagine an image that is 4 MB on disk will consume a lot more than 4 MBs.
The problem is that MFMailComposer displays the images in it's compose view when you add them as attachments and as a result they are decompressed, consuming memory. So your 4 MBs of images actually consume a lot more than you think they do.
Perhaps try sending only one image at a time. You also need to be conscious that you're releasing the images and the MFMailComposeViewController when you're done with them, or that would surely be the source of the leak.
Also be aware of how you initially load your images. UIImage's imageNamed: method actually caches images. Cached images are only purged in low memory situations, so they can hang around for a while if you're not hitting the limits.
Finally, you've noted that you're seeing the memory consumption in Instruments, but have you actually verified that it is actually a problem? Are you experiencing app crashes due to low memory when testing your app while it is not connected to Instruments or the debugger?
No body is perfect - and that goes for Apple too. There have been documented cases in the past where Apple's frameworks have shown memory leaks (UIImage's caching leaked in iOS 2.x), but I wouldn't be so quick to blame the frameworks when you notice a spike in memory consumption. If the leaks instrument is not showing any leaks, and the analyser isn't showing any issues, the likeliest scenario is that it's just simply memory consumption and not a leak.
Its important to remember that iOS devices don't have gigabytes of RAM like computers do. You need to be conservative with the memory that you use. If that means not sending XX MBs of images at the same time, then that's the way it has to be.

Related

UIImage Memory Problems

In my app I am returned from an API the urls of images, which I want to display in the app. This is all well and good, except I started to notice that when I am given, and load, very high-res images my app memory usage spikes 200+mb, often causing it to crash, which is unacceptable.
In one particular example, I am given an image that is of the dimensions 8100*5400 pixels. When the app loaded this image it crashed.
While I first thought the problem was a memory leak I created, but after doing some research, it seems like an unavoidable issue related to the size of the image -- since the image is 43,740,000 pixels and each pixel uses 4 bytes, the memory usage of the image will be a minimum of 174,960,000 bytes, or 174.96 megabytes.
The problem is i cannot control the size of the images sent by the api - they may be any resolution, possibly even larger. Obviously a UIImage will not work for my purposes.
Is there any other way I can display an image with a potentially massive resolution without causing app-crashing memory usage?
Instead of downloading the image as data into memory, which will crash your app, download it as data to disk, which will not.
You can then use the Image I/O framework to load a smaller version of the image which won't take up so much memory.
(Note that you should never attempt to display an image larger than the actual display size that you need, since that's a massive waste of memory. So, even if you can't help downloading the large image, you can at least load and display a version that is the actual much smaller size you need.)

CoreImage very high memory usage

When working with CIImage my memory jumps quite drastically by 50MB-60MB when creating the CIIMage and then my program crashes when I'm trying to create the UIImage result.
CIImage *image = [CIImage imageWithData:data]; // +50MB memory increase (data is jpeg data)
It doesn't happen all the time but it happens more frequently for larger images (3264x2448) and while the app is in background mode.
It leads to frequent crashes. Any ideas?
Core Image has severe limits on image size. iOS 8 lifts those limits to a very large extent; if you're on an earlier system, don't do that (i.e. confine yourself to smaller images). In iOS 7 and before, the GPU is available only for images less than 4K in size, which is very small indeed.
Moreover, use of core image in the background is severely limited, because, after all, how could your app dare to try to reach into the GPU, a small and busy place, from the background, when some foreground app may be using it? You are forced into using the CPU (though again, to some extent this restriction is lifted in iOS 8).
In all probability, therefore, your issues are partly memory related (you're trying to use core image for an image that's too big) and partly threading related (if you're using the CPU, you need to make sure you're on a background thread, because this is going to take a LOOOOONG time and the watchdog will kill you dead if you hang up the main thread).
Another thing to consider is how you're managing memory yourself. You haven't shown any relevant code so it's hard to say, but it may be that you are hanging on to data you don't need. You should show your code, and ideally you should analyze your app with Instruments so you know exactly where the problem lies.
For example, the only line of code you cite is
CIImage *image = [CIImage imageWithData:data]
This suggests you are holding the data in memory. That's totally unnecessary. If you play your cards right, you can get the CIImage straight from the image file on disk and create the output straight to disk without occupying any extra memory. If you are generating large memory just because you formed a CIImage, you might be doing it wrong (a CIImage is just a pointer, not a bitmap); the only moment where any memory is needed is the final rendering, where the bitmap is formed, and you can use ImageIO to get that out to disk without holding it in memory.

App crashes on launch with < 256 RAM iOS Devices

The Info
I recently launched an app on the AppStore. After testing on the simulator thousands of times, and actual devices hundreds of times we finally released our app.
The Problem
Reviews started popping up about app crashes when the user launches the app. We figured that the app crashes on launch on iOS devices with less than (or equal to) 256 Mb of RAM. The following devices are devices our app supports with less than 256:
iPod Touch 4G
iPhone 3GS
iPad 1
The app doesn't always crash. Sometimes it launches fine and runs smoothly. Other times it crashes. The time from launch (when the user taps the icon) to crash is usually two seconds, which would mean that the system isn't shutting it down.
Findings
When using Instruments to test on certain devices, I find the following:
There are no memory leaks (I'm using ARC), but there are memory warnings
Items are being allocated like crazy. There are so many allocated items, and even though I'm using ARC it's as if ARC isn't doing what it's supposed to be doing
Because of what I see as "over-allocation", the result is:
This app takes (on average) 60 MB of Real Memory and 166 MB of Virtual. When the app launches the memory being used quickly increases until it reaches about 60 MB at which point the view has been loaded.
Here is a snapshot of the Activity Monitor in Instruments:
I know that those figures are WAYY to high (although the CPU % never really gets up there). I am worried that ARC is not working properly, or the more likely case: I'm not allocating objects correctly. What could possibly be happening?
The Code and Warnings
In Xcode, there are only a few warnings, none of which pertain to the app launch or any files associated with the launching of the app. I placed breakpoints in both the App Delegate and my viewDidLoad method to check and see if the crash occurred there - it didn't.
More Background Info
Also, Xcode never generates any errors or messages in the debugger. There are also no crash reports in iTunes Connect, it just says, "Too few reports have been submitted for a report to be shown." I've added crash reporting to my app, but I haven't released that version.
A Few Questions
I started using Obj-C just as ARC arrived, so I'm new to dealing with memory, allocation, etc. (that is probably obvious) but I'd like to know a few things:
How can I use #autoreleasepool to reduce my memory impact? What do I do with memory warnings, what do I write in the didRecieveMemoryWarning since I'm using ARC?
Would removing NSLog statements help speed things up?
And the most important question:
Why does my app take up so much memory and how can I reduce my whopping 60 MB footprint?
I'd really appreciate any help! Thanks in advance!
EDIT: After testing on the iPhone 4 (A4), we noticed that the app doesn't crash when run whereas on devices with less than 256 MB of RAM it does.
I finally solved the issue. I spent a few hours pondering why my application could possibly take up more RAM than Angry Birds or Doodle Jump. That just didn't make sense, because my app does no CALayer Drawing, or complex Open GL Graphics Rendering, or heavy web connection.
I found this slideshow while searching for answers and slide 17 listed the ways to reduce memory footprint. One thing that stuck out was PNGCrush (Graphics Compression).
My app contains a lot of custom graphics (PNG files), but I hadn't thought of them affecting my app in any way, apparently images (when not optimized properly) severely increase an applications memory footprint.
After installing PNGCrush and using it on a particularly large image (3.2 MB) and then deleting a few unused images I ended up reducing my apps memory footprint from 60+ MB and severe lag to 35 MB and no lag. That took a whopping five minutes.
I haven't finished "crushing" all my images, but when I do I'll update everyone on the final memory footprint.
For all those interested, here is a link to a blog that explains how to install PNGCrush (it's rather complicated).
UPDATE: Instead of using the PNGCrush process (which is very helpful, although time consuming with lots of images) I now use a program called ImageOptim that provides a GUI for multiple scripts like PNGCrush. Heres a short description:
ImageOptim seamlessly integrates various optimisation tools: PNGOUT, AdvPNG, PNGCrush, extended OptiPNG, JpegOptim, jpegrescan, jpegtran, and Gifsicle.
Here's a link to the website with a free download for OS X 10.6 - 10.8. Note, I am not a developer, publisher or advertiser of this software.

recommended limit for memory management in Cocos2d?

is there a recommended limit for the images in Cocos2d, whether there are too big and take too much memory? Are there some rules, in dimensions or in Kb, to avoid slowing the game down? (for the background image, or the graphics of my characters (even if i use a batch node)?)
Thanks for your answer
First of all, memory usage has very, very, very little to do with performance. You can fill up the entire memory with textures, the game won't care. It's when you render them where there will be a difference. And then it only matters how much of the screen area you're filling with textures, how heavily they're overlayed, batched, rotated, scaled, shaded and alpha-blended. Those are the main factors in texture rendering performance. Memory usage plays a very insignificant role.
You may be interested in the cocos2d sprite-batch performance test I did and the general cocos2d performance analysis. Both come with test projects.
As for the maximum texture sizes have a look at the table from my Learn Cocos2D book:
Note that iPhone and iPhone 3G devices have a 24 MB texture memory limit. 3rd generation (iPhone 3GS) and newer devices don't have that limit anymore. Also keep in mind that while a device may have 256 MB of memory installed, significantly less memory will be available for use by apps.
For example, on the iPad (1st gen) it is recommended not to use more than 100 MB of memory, with a maximum available memory peaking at around 125 MB and memory warning starting to show as early as around 80-90 MB memory usage.
With iOS 5.1 Apple also increased the maximum texture size of the iPad 2. The safest and most commonly usable texture size is 2048x2048 for Retina textures, and 1024x1024 for standard resolution textures.
Not in the table are iPod touch devices because they're practically identical to the iPhone models of the same generation, but not as easily identifiable. For example the iPod touch 3rd generation includes devices with 8, 16 and 32GB of flash memory, but the 8GB model is actually 2nd generation hardware.
The dimensional size of images and textures depends on the device you are supporting. Older devices supported small layers, I think 2048x2048 in size. I don't think such limitation exists on current devices.
For large images, you definitely want to use batch nodes as they have been tested to demonstrate the largest performance gain when dealing with large images. Though it is a good idea to use them for as much as possible in general.
As for how much you can load, it really depends on the device. The new iPad has 1 GB of memory and is designed to have much more available memory for large images. A first-gen iPad has 1/4 this amount of memory, and in my experience I start to see an app crash when it gets around 100 MB of memory used (as confirmed using Instruments).
The trick is to use only as much memory as you need for the current app's operation, then release it when you move to a new scene or new set of images/sprites/textures. You could for example have very large tiled textures where only the tiles nearest the viewport are loaded into memory. You could technically have an infinite sized view that stretches forever if you remove from memory those parts of the view that are not visible onscreen.
And of course when dealing with lots of resources, make sure your app delegate responds appropriately to its memory warnings.
As per my knowledge.. A batch node of size 1024x1024 takes around 4 MB of space which is only texture memory.. And an application has maximum limit of 24 MB. So game slows down as you reach this 24 MB space and crashes after that. To avoid slowness I used maximum of 4 Batch Nodes at one time i.e.16 MB. Rest 8 MB was left for variables and other data. Before using more batch node I used to clean memory and remove unused batch nodes.. I don't know about memory limit in 4s but in case of iPhone 4 this was what I learnt.
Using this logic in mind I used to run my game smoothly.

COCOA Objects Allocation/Deallocation + Memory Optimization

Ah.. We've developed a good iPhone application. Now, 'm passing through last phases of it, i.e. profiling it and I've encountered few problems. Application has few leaks and objects occupying large memory chunks. We just checked somehow, application is not lowering its memory requirements and blocks remain occupied with creation of each View Controller.
Some of the views I really don't want after their disappearance, but they are not deallocated.
We're also downloading large files into iPhone through app but once we download very large file (> 10 MB), it crashes. Because after download we've also used thumbnail generation logic into which UIImage is created with 'contentsOfFile'..! So, app generally crashes after use of large files. We've used UIWebView for thumbnails.
My real problem is download, thumbnail, preview of larger files... clearing unnecessary memory (objects) once view is not in focus..!
Can anyone help me get rid of such problems easily???
I really don't wanna go through long long code..!
Thank You..!
As has been written hundreds of times on SO, use ASIHTTPRequest for networking, especially for large files. It can stream big files directly to disc so you don't run out of memory. As for creating a thumbnail of a >10mb file, it sounds like you would do yourself a favor by storing a thumbnail on the server instead.
If your views don't unload, something is wrong with your retain/release cycles. Have you implemented viewDidUnload on all your view controllers? Without more details, it's very hard to help.