0

I am trying to upload images data to the server, it uploaded successfully, but getting memory peaks on per image upload. And also uploading more than 20 images getting App shut's down and receiving memory warnings. UIImage data memory peaks

How to resolve this issue?

enter image description here

Edit: I am using NSURLConnection.

 image = [params valueForKey:key];
 partData = UIImageJPEGRepresentation([ImageUtility getQualityFilterImage:[params valueForKey:key]], 0.8f);
   if([partData isKindOfClass:[NSString class]])
          partData=[((NSString*)partData) dataUsingEncoding:NSUTF8StringEncoding];
                    [body appendData:partData];
            [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [urlRequest setHTTPBody:body];
iamVishal16
  • 1,780
  • 18
  • 40
  • You should show us how you're doing the upload. If you use `NSURLSession` upload task with either a file or stream (rather than a `NSData`), you will mitigate this problem. The key is avoid loading the entire asset into memory at any given point in time. – Rob Apr 08 '15 at 12:39
  • How you can upload image?can you please put your code here. – Nimit Parekh Apr 08 '15 at 12:41
  • Also, use Instruments allocation tool rather than the gauges in Xcode. It's a far more accurate measure of what's really going on (plus you can see precisely what's causing the growth in memory). – Rob Apr 08 '15 at 12:43
  • @NimitParekh Converting UIImage to NSData – iamVishal16 Apr 08 '15 at 12:44
  • 1
    @Vishu please post your code here if possible. – Nimit Parekh Apr 08 '15 at 12:46
  • Hello, Guys, why I am getting negative points in question? – iamVishal16 Apr 08 '15 at 12:56
  • 1
    Because you're asking us how to fix your code but you haven't shared your code with us, despite numerous requests. You have to show us what you're doing (or better, a [MCVE](http://stackoverflow.com/help/mcve)). Are you using `NSURLConnection`, `NSURLSession`, AFNetworking, etc.? And given the particular technology you're using, how are you using it? Right now, you're just showing us the symptoms of the problem, but not the source of the problem. – Rob Apr 08 '15 at 13:09
  • @Vishu make sure your project should be in ARC mode. – jigs Apr 08 '15 at 13:13
  • My project is ARC enables? – iamVishal16 Apr 08 '15 at 13:15
  • Yes, do that first and see 90% memory issues will be solved. – jigs Apr 08 '15 at 13:17
  • I mean to say my project has already ARC enabled. – iamVishal16 Apr 08 '15 at 13:18
  • Okay.. now check the image size which you want to upload. and try to compress that image first and upload that image. – jigs Apr 08 '15 at 13:19
  • @Rob I don't want to post all of my code. I think it is not necessary? – iamVishal16 Apr 09 '15 at 05:12
  • @Vishu No, definitely don't post all of your code. You generally want to post the bare minimum to allow people to reproduce the behavior you describe (see [MCVE](http://stackoverflow.com/help/mcve). For now, I think what you provided is adequate for us to at least understand what you're doing (manually building `NSMutableURLRequest` for multipart request). – Rob Apr 09 '15 at 18:02

3 Answers3

3

A couple of thoughts:

  1. If uploading multiple images, you might want to constrain how many you perform concurrently.

    For example, this is my memory when I issued 20 uploads of roughly 5mb per image, memory spiked up to 113 mb:

    enter image description here

    If, however, I constrained this to only doing no more than 4 at a time (using operation queues), the memory usage was improved, maxing out at 55mb (i.e. roughly 38mb over baseline):

    enter image description here

    Others have suggested that you might consider not doing more than one upload at a time, and that further reduces the peak memory usage further (in my example, peak memory usage was 27mb, only 10mb over baseline), but recognize that you pay a serious performance penalty for that.

  2. If using NSURLSession, if you use at upload task with the fromFile option rather than loading the asset into a NSData, even when doing 4 concurrently it used dramatically less memory, less than 1 mb over baseline:

    enter image description here

  3. I notice that you're using the Xcode gauges to analyze memory usage. I'd suggest using Instruments' Allocations tool (as shown above). The reason I suggest this is not only do I believe it to be more accurate, but more importantly, you seem to have some pattern of memory not falling completely back down to your baseline after performing some actions. This suggests that you might have some leaks. And only Instruments will help you identifying these leaks.

    I'd suggest watching WWDC 2013 video Fixing Memory Issues or WWDC 2012 video iOS App Performance: Memory which illustrate (amongst other things) how to use Instruments to identify memory problems.

  4. I notice that you're extracting the NSData from the UIImage objects. I don't know how you're getting the images, but if they're from your ALAssetsLibrary (or if you downloaded them from another resource), you might want to grab the original asset rather than loading it into a UIImage and then creating a NSData from that. If you use UIImageJPEGRepresentation, you invariably either (a) make the NSData larger than the original asset (making the memory issue worse); or (b) reduce the quality unnecessarily in an effort to make the NSData smaller. Plus you strip out much of the meta data.

    If you have to use UIImageJPEGRepresentation (e.g. it's a programmatically created UIImage), then so be it, do what you have to do. But if you have access to the original digital asset (e.g. see https://stackoverflow.com/a/27709329/1271826 for ALAssetsLibrary example), then do that. Quality may be maximized without making the asset larger than it needs to be.

Bottom line, you first want to make sure that you don't have any memory leaks, and then you want to minimize how much you hold in memory at any given time (not using any NSData if you can).

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
1

Memory peaks are harmless. You are going to get them when you are performing heavy uploads and downloads. But it should go back to its normal level later on, which is the case in the image you have posted. So i feel it is harmless and obvious in your case.

You should only worry when your application uses memory and doesnt release it later...

If you are performing heavy upload.. have a look at answer in this thread.

Community
  • 1
  • 1
Mayur Deshmukh
  • 1,169
  • 10
  • 25
0

Can you show your code ? Have you tried with NSURLSession ? I don't have problems with the memory if I upload photos with NSURLSession.

        NSURL *url = [NSURL URLWithString:@"SERVER"];

        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

        NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
        for (UIImage *image in self.arrayImages) {
           UIImage *imageToUPload = image;

           NSData *data = UIImagePNGRepresentation(imageToUPload);

           NSURLSessionUploadTask *task = [session uploadTaskWithRequest:[NSURLRequest requestWithURL:url] fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

           }];

           [task resume];
        }