将 UIImage 数据上传到服务器获取内存峰值?
Uploading UIImage data to the server getting memory peaks?
我正在尝试将图像数据上传到服务器,它已成功上传,但每次上传图像时都会出现内存峰值。并且还上传了 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];
内存峰值是无害的。当您执行大量上传和下载时,您将获得它们。但是它应该稍后恢复到正常水平,您发布的图像就是这种情况。所以我觉得你的情况是无害的,而且很明显。
你应该只担心当你的应用程序使用内存并且稍后不释放它时...
如果您正在执行大量上传..请查看 this thread 中的答案。
你能展示一下你的代码吗?您是否尝试过 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];
}
几个想法:
如果上传多张图片,您可能希望限制同时执行的图片数量。
例如,这是我的内存,当我发出 20 次上传,每张图片大约 5mb,内存飙升至 113mb:
但是,如果我将此限制为一次只执行不超过 4 个(使用操作队列),则内存使用量得到改善,最大为 55mb(即超过基线约 38mb):
其他人建议您可以考虑一次不进行多个上传,这样可以进一步降低峰值内存使用量(在我的示例中,峰值内存使用量为 27mb,仅比基线高 10mb),但要认识到你为此付出了严重的性能损失。
如果使用 NSURLSession
,如果您使用带 fromFile
选项的上传任务而不是将资产加载到 NSData
,即使同时执行 4 个任务它使用的内存大大减少,比基线少了不到 1 mb:
我注意到您正在使用 Xcode 仪表分析内存使用情况。我建议使用 Instruments 的分配工具(如上所示)。我建议这样做的原因不仅是我认为它更准确,而且更重要的是,您似乎有某种记忆模式在执行某些操作后不会完全回落到您的基线。这表明您可能有一些泄漏。并且只有 Instruments 可以帮助您识别这些泄漏。
我建议观看 WWDC 2013 视频 Fixing Memory Issues or WWDC 2012 video iOS App Performance: Memory,其中说明(除其他外)如何使用 Instruments 识别内存问题。
我注意到您正在从 UIImage
对象中提取 NSData
。我不知道您是如何获取图像的,但是如果它们来自您的 ALAssetsLibrary
(或者如果您是从其他资源下载的),您可能想要获取原始资产而不是将其加载到UIImage
然后从中创建一个 NSData
。如果您使用 UIImageJPEGRepresentation
,您总是要么 (a) 使 NSData
大于原始资产(使内存问题更糟);或 (b) 不必要地降低质量以使 NSData
更小。另外,您删除了大部分元数据。
如果您必须使用 UIImageJPEGRepresentation
(例如,它是通过编程创建的 UIImage
),那么就这样吧,做您必须做的。但是,如果您有权访问原始数字资产(例如,请参阅 中的 ALAssetsLibrary
示例),然后执行此操作。可以在不使资产超过其需要的情况下最大化质量。
最重要的是,您首先要确保没有任何内存泄漏,然后您要在任何给定时间尽量减少内存中的内存量(不使用任何 NSData
如果你可以)。
我正在尝试将图像数据上传到服务器,它已成功上传,但每次上传图像时都会出现内存峰值。并且还上传了 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];
内存峰值是无害的。当您执行大量上传和下载时,您将获得它们。但是它应该稍后恢复到正常水平,您发布的图像就是这种情况。所以我觉得你的情况是无害的,而且很明显。
你应该只担心当你的应用程序使用内存并且稍后不释放它时...
如果您正在执行大量上传..请查看 this thread 中的答案。
你能展示一下你的代码吗?您是否尝试过 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];
}
几个想法:
如果上传多张图片,您可能希望限制同时执行的图片数量。
例如,这是我的内存,当我发出 20 次上传,每张图片大约 5mb,内存飙升至 113mb:
但是,如果我将此限制为一次只执行不超过 4 个(使用操作队列),则内存使用量得到改善,最大为 55mb(即超过基线约 38mb):
其他人建议您可以考虑一次不进行多个上传,这样可以进一步降低峰值内存使用量(在我的示例中,峰值内存使用量为 27mb,仅比基线高 10mb),但要认识到你为此付出了严重的性能损失。
如果使用
NSURLSession
,如果您使用带fromFile
选项的上传任务而不是将资产加载到NSData
,即使同时执行 4 个任务它使用的内存大大减少,比基线少了不到 1 mb:我注意到您正在使用 Xcode 仪表分析内存使用情况。我建议使用 Instruments 的分配工具(如上所示)。我建议这样做的原因不仅是我认为它更准确,而且更重要的是,您似乎有某种记忆模式在执行某些操作后不会完全回落到您的基线。这表明您可能有一些泄漏。并且只有 Instruments 可以帮助您识别这些泄漏。
我建议观看 WWDC 2013 视频 Fixing Memory Issues or WWDC 2012 video iOS App Performance: Memory,其中说明(除其他外)如何使用 Instruments 识别内存问题。
我注意到您正在从
UIImage
对象中提取NSData
。我不知道您是如何获取图像的,但是如果它们来自您的ALAssetsLibrary
(或者如果您是从其他资源下载的),您可能想要获取原始资产而不是将其加载到UIImage
然后从中创建一个NSData
。如果您使用UIImageJPEGRepresentation
,您总是要么 (a) 使NSData
大于原始资产(使内存问题更糟);或 (b) 不必要地降低质量以使NSData
更小。另外,您删除了大部分元数据。如果您必须使用
UIImageJPEGRepresentation
(例如,它是通过编程创建的UIImage
),那么就这样吧,做您必须做的。但是,如果您有权访问原始数字资产(例如,请参阅 中的ALAssetsLibrary
示例),然后执行此操作。可以在不使资产超过其需要的情况下最大化质量。
最重要的是,您首先要确保没有任何内存泄漏,然后您要在任何给定时间尽量减少内存中的内存量(不使用任何 NSData
如果你可以)。