使用@autoreleasepool减少峰值内存使用量

Joe*_*Joe 7 memory-management objective-c nsautoreleasepool ios automatic-ref-counting

我在一个iPad应用程序上工作,该应用程序具有一个紧密循环使用Web服务和Core Data的同步过程.为了根据Apple的Recomendation减少内存占用,我会NSAutoreleasePool定期分配和排空.这当前效果很好,当前应用程序没有内存问题.但是,我打算转移到NSAutoreleasePool不再有效的ARC,并希望保持同样的性能.我创建了一些示例并计算了它们,我想知道使用ARC的最佳方法是什么,以实现相同的性能并保持代码可读性.

出于测试目的,我想出了3个场景,每个场景使用1到10,000,000之间的数字创建一个字符串.我运行了每个例子3次,以确定他们使用带有Apple LLVM 3.0编译器(w/o gdb -O0)和XCode 4.2的Mac 64位应用程序花了多长时间.我还通过仪器运行每个示例,以大致了解内存峰值.

以下每个示例都包含在以下代码块中:

int main (int argc, const char * argv[])
{
    @autoreleasepool {
        NSDate *now = [NSDate date];

        //Code Example ...

        NSTimeInterval interval = [now timeIntervalSinceNow];
        printf("Duration: %f\n", interval);
    }
}
Run Code Online (Sandbox Code Playgroud)

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];
Run Code Online (Sandbox Code Playgroud)

运行时间:
10.928158
10.912849
11.084716


外部@autoreleasepool(峰值内存:~382 MB)

    @autoreleasepool {
        for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++)
        {
            NSString *text = [NSString stringWithFormat:@"%u", count + 1U];
            [text class];
        }
    }
Run Code Online (Sandbox Code Playgroud)

运行时间:
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];
        }
    }
Run Code Online (Sandbox Code Playgroud)

运行时间:
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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

运行时间:
10.908756
10.960189
11.018382

goto声明提供了最接近的表现,但它使用了一个goto.有什么想法吗?

更新:

注意:该goto语句是@autoreleasepool的正常退出,如文档中所述,不会泄漏内存.

在进入时,推送自动释放池.在正常退出(break,return,goto,fall-through等)时,将弹出自动释放池.为了与现有代码兼容,如果exit是由异常引起的,则不会弹出自动释放池.

ipm*_*mcc 9

如果没有以下内容,以下内容应该与goto答案相同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];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)