How to create/end run loop to properly deallocate memory?

152 views Asked by At

In my ARC iOS app I am running a for loop that ends up with a large memory allocation overhead. I want to somehow end my for loop with minimal/no extra memory allocated. In this instance I am using the SSKeychain library which lets me fetch things from a keychain. I usually just use autorelease pools and get my memory removed properly but here I don't know what is wrong because I end up with 70 mb + of memory allocated at the end of the loop. I have been told that I should start/end a run loop to properly deal with this. Thoughts?

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];
            } 
}
1

There are 1 answers

8
Jody Hagins On

What are you using to measure memory usage?

Results of a very simple test...

Running in the simulator, measure only resident memory before and after.

Without autoreleasepool... Started with 27254784, ended with 30212096, used 2957312

With autoreleasepool... Started with 27316224, ended with 27443200, used 126976

Obviously, the autoreleasepool is preventing memory from growing too bad, and I don't see anything close to 70MB being used under any circumstance.

You should run instruments and get some good readings on the behavior.

Here is the code I hacked and ran...

The memchecker

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;
}

And the code...

#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;
}