【问题标题】:Uploading UIImage data to the server getting memory peaks?将 UIImage 数据上传到服务器会出现内存峰值?
【发布时间】:2015-04-08 12:33:54
【问题描述】:

我正在尝试将图像数据上传到服务器,它已成功上传,但每次上传图像时都会出现内存峰值。还上传了 20 多张图片,让 App 关闭并收到内存警告。

如何解决这个问题?

编辑: 我正在使用 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];

【问题讨论】:

  • 您应该向我们展示您是如何进行上传的。如果您将NSURLSession 上传任务与文件或流(而不是NSData)一起使用,您将缓解此问题。关键是避免在任何给定时间点将整个资产加载到内存中。
  • 如何上传图片?请把代码放在这里。
  • 另外,使用 Instruments 分配工具而不是 Xcode 中的仪表。它可以更准确地衡量实际发生的情况(而且您可以准确地看到导致内存增长的原因)。
  • @Vishu 如果可能,请在此处发布您的代码。
  • 因为您在询问我们如何修复您的代码,但您没有与我们分享您的代码,尽管有很多请求。你必须向我们展示你在做什么(或者更好,MCVE)。您在使用NSURLConnectionNSURLSession、AFNetworking 等吗?鉴于您正在使用的特定技术,您是如何使用它的?现在,您只是向我们展示了问题的症状,而不是问题的根源。

标签: ios objective-c xcode uiimage memory-pressure


【解决方案1】:

一些想法:

  1. 如果上传多张图片,您可能需要限制同时执行的数量。

    例如,这是我上传 20 次,每张图片大约 5mb 的内存,内存飙升至 113mb:

    但是,如果我将其限制为一次只执行不超过 4 个(使用操作队列),则内存使用率会得到改善,最大为 55mb(即比基线高出大约 38mb):

    其他人建议您可能考虑一次不要上传多个文件,这会进一步降低峰值内存使用量(在我的示例中,峰值内存使用量为 27mb,仅比基线高出 10mb),但认识到您为此付出严重的性能损失。

  2. 如果使用NSURLSession,如果您使用带有fromFile 选项的上传任务而不是将资产加载到NSData,即使同时执行4 个,它使用的内存也大大减少,比基线少1 mb:

  3. 我注意到您正在使用 Xcode 仪表来分析内存使用情况。我建议使用 Instruments 的 Allocations 工具(如上所示)。我建议这样做的原因不仅是我认为它更准确,而且更重要的是,在执行某些操作后,您似乎有某种记忆模式并没有完全回落到您的基线。这表明您可能有一些泄漏。只有 Instruments 才能帮助您识别这些泄漏。

    我建议观看 WWDC 2013 视频 Fixing Memory Issues 或 WWDC 2012 视频 iOS App Performance: Memory,其中说明(除其他外)如何使用 Instruments 来识别内存问题。

  4. 我注意到您正在从 UIImage 对象中提取 NSData。我不知道您是如何获取图像的,但如果它们来自您的 ALAssetsLibrary(或者如果您从其他资源下载它们),您可能想要获取原始资产而不是将其加载到 @987654333 @ 然后从中创建一个NSData。如果你使用UIImageJPEGRepresentation,你总是(a)使NSData大于原始资产(使内存问题更严重);或 (b) 不必要地降低质量以使NSData 更小。此外,您还去除了大部分元数据。

    如果你必须使用UIImageJPEGRepresentation(例如,它是一个以编程方式创建的UIImage),那就这样吧,做你必须做的。但是,如果您有权访问原始数字资产(例如,请参阅 https://stackoverflow.com/a/27709329/1271826 以获取 ALAssetsLibrary 示例),那么就这样做。可以在不使资产大于所需大小的情况下最大限度地提高质量。

最重要的是,您首先要确保没有任何内存泄漏,然后您希望在任何给定时间最小化内存中的内存量(如果可以,不要使用任何NSData)。

【讨论】:

  • 谢谢,很好的解释。
  • 第二个想法大大减少了我的内存使用量。谢谢!
【解决方案2】:

内存峰值是无害的。当您执行大量上传和下载时,您将获得它们。但它应该稍后会恢复到正常水平,您发布的图像就是这种情况。所以我觉得在你的情况下它是无害且显而易见的。

您应该只担心您的应用程序使用内存并且以后不释放它...

如果您正在执行大量上传。请查看this thread 中的答案。

【讨论】:

  • 但是当我尝试上传超过 20 张图片时,我的应用程序关闭了?
  • 您是在一个请求中发送所有这些吗?如果没有,我会要求您发布我们的上传代码
  • 是的,我在一个请求中发送所有这些?
  • 你在使用 NSURLSession 吗?
  • 不,我不使用 NSURLSession?
【解决方案3】:

你能展示你的代码吗?你试过 NSURLSession 吗?如果我使用 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];
        }

【讨论】:

  • 是单文件还是多文件?
  • 只针对单个文件,但你可以把代码放在一个bucle中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 2012-04-25
  • 2015-07-11
相关资源
最近更新 更多