在iOS中通过HTTP获取图像时不断增长的内存分配 [英] Constantly growing memory allocation while fetching images over HTTP in iOS

查看:113
本文介绍了在iOS中通过HTTP获取图像时不断增长的内存分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个需要通过HTTP获取大量图像的iOS应用程序。我已经尝试了几种方法,但独立完成了我的工作,Instuments显示不断增加的内存分配,并且当我在设备上运行时,应用程序迟早会崩溃。仪器没有泄漏。

I am implementing an iOS App that needs to fetch a huge amount of images over HTTP. I've tried several approaches but independently what I do, Instuments shows constantly increasing memory allocations and the App crashes sooner or later when I run it on a device. There are no leaks shown by Instruments.

到目前为止,我尝试了以下方法:

So far I have tried the following approches:


  • 使用NSOperation中的同步NSURLConnection获取图像

  • 使用NSOperation中的异步NSURLConnection获取图像

  • 使用提取图像主线程中的[NSData dataWithContentsOfURL:url]

  • 在NSOperation中使用同步ASIHTTPRequest获取图像

  • 使用异步ASIHTTPRequest获取图像并添加它是一个NSOperationQueue

  • 使用异步ASIHTTPRequest获取图像并使用completionBlock

  • Fetch the images using a synchronous NSURLConnection within an NSOperation
  • Fetch the images using a asynchronous NSURLConnection within an NSOperation
  • Fetch the images using [NSData dataWithContentsOfURL:url] in the Main-Thread
  • Fetch the images using synchronous ASIHTTPRequest within an NSOperation
  • Fetch the images using asynchronous ASIHTTPRequest and adding it to a NSOperationQueue
  • Fetch the images using asynchronous ASIHTTPRequest and using a completionBlock

电话Instrumetns中的树显示在处理HTTP响应时消耗了内存。在异步NSURLConnection的情况下,这是在

The Call Tree in Instrumetns shows that the memory is consumed while processing the HTTP-Response. In case of asynchronous NSURLConnection this is in

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
}  

如果是同步NSURLConnection,Instruments会显示不断增长的CFData(商店)条目。
ASIHTTPRequest的问题似乎与类似代码位置中的异步NSURLConnection相同。 [NSData dataWithContentsOfURL:url]方法在该语句中显示了越来越多的总内存分配。

In case of the synchronous NSURLConnection, Instruments shows a growing CFData (store) entry. The problem with ASIHTTPRequest seems to be the same as with the asynchronous NSURLConnection in a analogous code-position. The [NSData dataWithContentsOfURL:url] approach shows an increasing amount of total memory allocation in exactely that statement.

当请求在单独的线程中完成时,我正在使用NSAutoReleasePool我试图用[[NSURLCache sharedURLCache] removeAllCachedResponses]释放内存 - 没有成功。

I am using an NSAutoReleasePool when the request is done in a separate thread and I have tried to free up memory with [[NSURLCache sharedURLCache] removeAllCachedResponses] - no success.

任何解决问题的想法/提示?谢谢。

Any ideas/hints to solve the problem? Thanks.

编辑:
如果我使用CoreData保留图像,则只会显示此行为。以下是我作为NSInvocationOperation运行的代码:

The behaviour only shows up if I persist the images using CoreData. Here is the code I run as a NSInvocationOperation:

-(void) _fetchAndSave:(NSString*) imageId {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *url = [NSString stringWithFormat:@"%@%@", kImageUrl, imageId];
HTTPResponse *response = [SimpleHTTPClient GET:url headerOrNil:nil];
NSData *data = [response payload];

if(data && [data length] > 0) {
    UIImage *thumbnailImage = [UIImage imageWithData:data];
    NSData *thumbnailData = UIImageJPEGRepresentation([thumbnailImage scaleToSize:CGSizeMake(55, 53)], 0.5); // UIImagePNGRepresentation(thumbnail); 

    [self performSelectorOnMainThread:@selector(_save:) withObject:[NSArray arrayWithObjects:imageId, data, thumbnailData, nil] waitUntilDone:NO];
}
[pool release];
}

所有与CoreData相关的东西都在主线程中完成,所以应该不是任何CoreData多线程问题。但是,如果我保留图像,仪器会在上述位置显示不断增加的内存分配。

All CoreData related stuff is done in the Main-Thread here, so there should not be any CoreData multithreading issue. However, if I persist the images, Instruments shows constantely increasing memory allocations at the positions described above.

编辑II:

CoreData相关代码:

CoreData related code:

-(void) _save:(NSArray*)args {
NSString *imageId = [args objectAtIndex:0];
NSData *data = [args objectAtIndex:1];
NSData *thumbnailData = [args objectAtIndex:2];

Image *image = (Image*)[[CoreDataHelper sharedSingleton] createObject:@Image];
image.timestamp =  [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
image.data = data;

Thumbnail *thumbnail = (Thumbnail*)[[CoreDataHelper sharedSingleton] createObject:@"Thumbnail"];
thumbnail.data = thumbnailData;
thumbnail.timestamp = image.timestamp;
[[CoreDataHelper sharedSingleton] save];
}

来自CoreDataHelper(self.managedObjectContext正在挑选当前线程中可用的NSManagedObjectContext) :

From CoreDataHelper (self.managedObjectContext is picking the NSManagedObjectContext usable in the current thread):

-(NSManagedObject *) createObject:(NSString *) entityName {
return [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:self.managedObjectContext];
}


推荐答案

我们遇到了类似的问题。在通过http获取大量图像的同时,内存分配中出现了巨大的增长和锯齿模式。我们会看到,系统或多或少会随着时间的推移进行清理,但速度很慢,而且不可预测。与此同时,下载量正在流入,堆积在内存上的任何内容上。内存分配将达到200M左右,然后我们就会死亡。

We had a similar problem. While fetching lots of images over http, there was huge growth and a sawtooth pattern in the memory allocation. We'd see the system clean up, more or less, as it went, but slowly, and not predictably. Meanwhile the downloads were streaming in, piling up on whatever was holding onto the memory. Memory allocation would crest around 200M and then we'd die.

问题是NSURLCache问题。你声明你试过[[NSURLCache sharedURLCache] removeAllCachedResponses]。我们也试过了,但后来尝试了一些不同的东西。

The problem was an NSURLCache issue. You stated that you tried [[NSURLCache sharedURLCache] removeAllCachedResponses]. We tried that, too, but then tried something a little different.

我们的下载是在 N 图像/电影的组中完成的,其中 N 通常为50到500.重要的是我们将所有 N 作为原子操作。

Our downloads are done in groups of N images/movies, where N was typically 50 to 500. It was important that we get all of N as an atomic operation.

在开始我们的http下载组之前,我们这样做了:

Before we started our group of http downloads, we did this:

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:0];
[NSURLCache setSharedURLCache:sharedCache];

然后我们通过同步调用通过http获取 N 中的每个图像。我们在NSOperation中进行此组下载,因此我们不会阻止UI。

We then get each image in N over http with a synchronous call. We do this group download in an NSOperation, so we're not blocking the UI.

NSData *movieReferenceData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

最后,在每个单独的图像下载之后,以及我们完成该图像的NSData对象之后,我们称之为:

Finally, after each individual image download, and after we're done with our NSData object for that image, we call:

[sharedCache removeAllCachedResponses]; 

我们的内存分配峰值行为下降到非常舒适的少数几兆字节,并且停止增长。

Our memory allocation peak behavior dropped to a very comfortable handful of megabytes, and stopped growing.

这篇关于在iOS中通过HTTP获取图像时不断增长的内存分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆