I was just wondering, why is there no autorelease pool optimization under the ARC compiler, where it would retain an object in the innermost scope, remove it from the autorelease pool and release once the object is no longer in use?
To quote a very impractical example from another question,
for(NSUInteger i = 0; i < 10000; i++)
{
for(NSUInteger j = 0; j < 10000; j++)
{
NSNumber* n = [NSNumber numberWithUnsignedInteger:j];
//NSLog(@"%@", n); //Disabled this to increase memory bloat faster.
}
}
Without @autoreleasepool { ... }
wrapping, memory grows and grows. Wrapping with @autoreleasepool
, memory remains low:
for(NSUInteger i = 0; i < 10000; i++)
{
for(NSUInteger j = 0; j < 10000; j++)
{
@autoreleasepool {
NSNumber* n = [NSNumber numberWithUnsignedInteger:j];
//NSLog(@"%@", n); //Disabled this to increase memory bloat faster.
}
}
}
But why can't the compiler optimize cases like these, where the objects will not be needed beyond the innermost scope and remove the need of the @autoreleasepool
wrapping? Is there a technical reason this is not possible or has not been done yet?
Edit
To clarify, why can't the compiler output a code like the following:
for(NSUInteger i = 0; i < 10000; i++)
{
for(NSUInteger j = 0; j < 10000; j++)
{
NSNumber* n = [NSNumber numberWithUnsignedInteger:j];
objc_retain(n);
objc_removeFromAutoreleasePool(n);
NSLog(@"%@", n);
objc_release(n);
}
}
Edit 2
At the request of Greg, here are the disassembly results of both examples above.
Without @autoreleasepool { }
:
TestOpt`-[LMViewController testAutoreleaseMem] at LMViewController.m:17:
0x2187: pushl %ebp
0x2188: movl %esp, %ebp
0x218a: pushl %ebx
0x218b: pushl %edi
0x218c: pushl %esi
0x218d: subl $0x1c, %esp
0x2190: calll 0x2195 ; -[LMViewController testAutoreleaseMem] + 14 at LMViewController.m:17
0x2195: popl %esi
0x2196: xorl %eax, %eax
0x2198: movl 0x13cb(%esi), %ebx
0x219e: movl %eax, -0x10(%ebp)
0x21a1: xorl %edi, %edi
0x21a3: movl 0x13df(%esi), %eax
0x21a9: movl %edi, 0x8(%esp)
0x21ad: movl %ebx, 0x4(%esp)
0x21b1: movl %eax, (%esp)
0x21b4: calll 0x227e ; symbol stub for: objc_msgSend
0x21b9: movl %eax, (%esp)
0x21bc: calll 0x2296 ; symbol stub for: objc_retainAutoreleasedReturnValue
0x21c1: movl %eax, (%esp)
0x21c4: calll 0x228a ; symbol stub for: objc_release
0x21c9: incl %edi
0x21ca: cmpl $0x2710, %edi
0x21d0: jne 0x21a3 ; -[LMViewController testAutoreleaseMem] + 28 at LMViewController.m:24
0x21d2: movl -0x10(%ebp), %eax
0x21d5: incl %eax
0x21d6: cmpl $0x2710, %eax
0x21db: jne 0x219e ; -[LMViewController testAutoreleaseMem] + 23 at LMViewController.m:24
0x21dd: addl $0x1c, %esp
0x21e0: popl %esi
0x21e1: popl %edi
0x21e2: popl %ebx
0x21e3: popl %ebp
0x21e4: ret
With:
TestOpt`-[LMViewController testAutoreleaseMem] at LMViewController.m:17:
0x216f: pushl %ebp
0x2170: movl %esp, %ebp
0x2172: pushl %ebx
0x2173: pushl %edi
0x2174: pushl %esi
0x2175: subl $0x1c, %esp
0x2178: calll 0x217d ; -[LMViewController testAutoreleaseMem] + 14 at LMViewController.m:17
0x217d: popl %ecx
0x217e: movl %ecx, -0x10(%ebp)
0x2181: xorl %eax, %eax
0x2183: movl 0x13e3(%ecx), %ecx
0x2189: movl %eax, -0x14(%ebp)
0x218c: xorl %edi, %edi
0x218e: movl %ecx, %ebx
0x2190: calll 0x2278 ; symbol stub for: objc_autoreleasePoolPush
0x2195: movl %eax, %esi
0x2197: movl -0x10(%ebp), %eax
0x219a: movl 0x13f7(%eax), %eax
0x21a0: movl %edi, 0x8(%esp)
0x21a4: movl %ebx, 0x4(%esp)
0x21a8: movl %eax, (%esp)
0x21ab: calll 0x227e ; symbol stub for: objc_msgSend
0x21b0: movl %eax, (%esp)
0x21b3: calll 0x2296 ; symbol stub for: objc_retainAutoreleasedReturnValue
0x21b8: movl %eax, (%esp)
0x21bb: calll 0x228a ; symbol stub for: objc_release
0x21c0: movl %esi, (%esp)
0x21c3: calll 0x2272 ; symbol stub for: objc_autoreleasePoolPop
0x21c8: incl %edi
0x21c9: cmpl $0x2710, %edi
0x21cf: jne 0x2190 ; -[LMViewController testAutoreleaseMem] + 33 at LMViewController.m:23
0x21d1: movl %ebx, %ecx
0x21d3: movl -0x14(%ebp), %eax
0x21d6: incl %eax
0x21d7: cmpl $0x2710, %eax
0x21dc: jne 0x2189 ; -[LMViewController testAutoreleaseMem] + 26 at LMViewController.m:24
0x21de: addl $0x1c, %esp
0x21e1: popl %esi
0x21e2: popl %edi
0x21e3: popl %ebx
0x21e4: popl %ebp
0x21e5: ret