使用@autoreleasepool减少峰值内存使用量 [英] Reduce Peak Memory Usage With @autoreleasepool
问题描述
我在一个iPad应用程序上工作,该应用程序具有一个紧密循环使用Web服务和Core Data的同步过程。根据 Apple的推荐我定期分配并消耗 NSAutoreleasePool
。这当前效果很好,当前应用程序没有内存问题。但是,我打算转移到ARC,其中 NSAutoreleasePool
不再有效,并希望保持同样的性能。我创建了一些示例并计算了它们并且我想知道什么是最好的方法,使用ARC来实现相同的性能并保持代码可读性。
I work on an iPad application that has a sync process that uses web services and Core Data in a tight loop. To reduce the memory footprint according to Apple's Recomendation I allocate and drain an NSAutoreleasePool
periodically. This currently works great and there are no memory issues with the current application. However, I plan on moving to ARC where the NSAutoreleasePool
is no longer valid and would like to maintain this same kind of performance. I created a few examples and timed them and I am wondering what is the best approach, using ARC, to acheive the same kind of performance and maintain code readability.
出于测试目的,我想出了3个场景,每个场景使用1到10,000,000之间的数字创建一个字符串。我运行了每个例子3次,以确定他们使用带有Apple LLVM 3.0编译器(w / o gdb -O0)和XCode 4.2的Mac 64位应用程序花了多长时间。我还通过工具运行每个示例,以大致了解内存峰值。
For testing purposes I came up with 3 scenarios, each create a string using a number between 1 and 10,000,000. I ran each example 3 times to determine how long they took using a Mac 64 bit application with the Apple LLVM 3.0 compiler (w/o gdb -O0) and XCode 4.2. I also ran each example through instruments to see roughly what the memory peak was.
以下每个示例都包含在以下代码块中:
Each of the examples below are contained within the following code block:
int main (int argc, const char * argv[])
{
@autoreleasepool {
NSDate *now = [NSDate date];
//Code Example ...
NSTimeInterval interval = [now timeIntervalSinceNow];
printf("Duration: %f\n", interval);
}
}
NSAutoreleasePool批次[原始预ARC](峰值内存:~116 KB)
static const NSUInteger BATCH_SIZE = 1500;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++)
{
NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
[text class];
if((count + 1) % BATCH_SIZE == 0)
{
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
}
}
[pool drain];
运行时间
10.928158
10.912849
11.084716
Outer @autoreleasepool(峰值记忆:~382 MB)
@autoreleasepool {
for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++)
{
NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
[text class];
}
}
运行时间:
11.489350
11.310462
11.344662
内部@autoreleasepool(峰值记忆:~61.2KB)
for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++)
{
@autoreleasepool {
NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
[text class];
}
}
运行时间:
14.031112
14.284014
14.099625
@autoreleasepool w / goto(峰值记忆:~115KB)
static const NSUInteger BATCH_SIZE = 1500;
uint32_t count = 0;
next_batch:
@autoreleasepool {
for(;count < MAX_ALLOCATIONS; count++)
{
NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
[text class];
if((count + 1) % BATCH_SIZE == 0)
{
count++; //Increment count manually
goto next_batch;
}
}
}
运行时间:
10.908756
10.960189
11.018382
goto
语句提供最接近的性能,但它使用转到
。有什么想法吗?
The goto
statement offered the closest performance, but it uses a goto
. Any thoughts?
更新:
注意: goto
语句是@autoreleasepool的正常退出,如文档并且不会泄漏内存。
Note: The goto
statement is a normal exit for an @autoreleasepool as stated in the documentation and will not leak memory.
在输入时,会推送自动释放池。在正常退出(break,
return,goto,fall-through等)时,将弹出自动释放池。
为了与现有代码兼容,如果退出是由于异常引起的,则
不会弹出自动释放池。
On entry, an autorelease pool is pushed. On normal exit (break, return, goto, fall-through, and so on) the autorelease pool is popped. For compatibility with existing code, if exit is due to an exception, the autorelease pool is not popped.
推荐答案
如果没有 goto $ c $,以下内容应与
goto
答案相同c>:
The following should achieve the same thing as the goto
answer without the goto
:
for (NSUInteger count = 0; count < MAX_ALLOCATIONS;)
{
@autoreleasepool
{
for (NSUInteger j = 0; j < BATCH_SIZE && count < MAX_ALLOCATIONS; j++, count++)
{
NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
[text class];
}
}
}
这篇关于使用@autoreleasepool减少峰值内存使用量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!