0

在我的 ARC iOS 应用程序中,我正在运行一个 for 循环,最终导致大量内存分配开销。我想以某种方式以最少/不分配额外内存的方式结束我的 for 循环。在这种情况下,我使用的是 SSKeychain 库,它可以让我从钥匙串中获取东西。我通常只使用自动释放池并正确删除我的内存,但在这里我不知道出了什么问题,因为我最终在循环结束时分配了 70 mb + 的内存。我被告知我应该开始/结束一个运行循环来正确处理这个问题。想法?

for (int i = 0; i < 10000; ++i) {
            @autoreleasepool {
                NSError *  error2 = nil;
                SSKeychainQuery*  query2 = [[SSKeychainQuery alloc] init];
                query2.service = @"Eko";
                query2.account = @"loginPINForAccountID-2";
                query2.password = nil;
                [query2 fetch:&error2];
            } 
}
4

1 回答 1

1

你用什么来衡量内存使用情况?

一个非常简单的测试结果...

在模拟器中运行,只测量前后的常驻内存。

没有自动释放池...以 27254784 开头,以 30212096 结尾,使用 2957312

使用 autoreleasepool... 以 27316224 开始,以 27443200 结束,使用 126976

显然,自动释放池正在防止内存增长太糟糕,而且在任何情况下我都看不到任何接近 70MB 的内存被使用。

您应该运行仪器并获得有关行为的一些良好读数。

这是我破解并运行的代码...

内存检查器

static NSUInteger available_memory(void) {
    NSUInteger result = 0;
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size) == KERN_SUCCESS) {
        result = info.resident_size;
    }
    return result;
}

而且代码...

#define USE_AUTORELEASE_POOL 1

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSUInteger beginMemory = available_memory();
        for (int i = 0; i < 10000; ++i) {
#ifdef USE_AUTORELEASE_POOL
            @autoreleasepool
#endif
            {
                NSError *  error2 = nil;
                SSKeychainQuery*  query2 = [[SSKeychainQuery alloc] init];
                query2.service = @"Eko";
                query2.account = @"loginPINForAccountID-2";
                query2.password = nil;
                [query2 fetch:&error2];
            }
        }
        NSUInteger endMemory = available_memory();

        NSLog(@"Started with %u, ended with %u, used %u", beginMemory, endMemory, endMemory-beginMemory);
    });

    return YES;
}
于 2015-10-21T22:47:07.573 回答