使用@autoreleasepool减少峰值内存使用量 [英] Reduce Peak Memory Usage With @autoreleasepool

查看:125
本文介绍了使用@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 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屋!

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