我只是想知道,爲什麼在ARC編譯器下沒有自動釋放池優化,它會在最內層的作用域中保留一個對象,將它從自動釋放池中移除,不再使用?在ARC編譯器下缺少自動釋放優化
從另一個問題舉一個很不切實際的例子,
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.
}
}
沒有@autoreleasepool { ... }
包裝,存儲增長和增長。與@autoreleasepool
包裝,內存仍然很低:
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.
}
}
}
但爲什麼不能編譯器優化這樣的情況下,其中的對象將不再需要超出最裏面的範圍和去除@autoreleasepool
包裝的需求?有沒有技術上的原因,這是不可能的或尚未完成?
編輯
爲了澄清,爲什麼不能編譯器輸出如下所示的代碼:
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);
}
}
編輯2
在格雷格的請求,這裏有以上兩個例子的反彙編結果。
沒有@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
有了:
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
如果您使用了alloc/initWith ...它將有機會插入發佈...+ numberWith將始終返回一個自動釋放對象。所以它會被游泳池保留。 –
@GradyPlayer我知道它是如何工作的。我在問爲什麼不能將該對象從池中刪除,因此一旦範圍結束就會被釋放? –
ARC認爲這是一個奇蹟。我們不要選尼特。 –