原文地址:http://yangchao0033.github.io/blog/2015/12/31/guan-yu-at-autoreleasepoolde-ce-shi-ji-shi-yong/
首先,我們先對使用autoreleasepool的場景進行性能對比。
- 不用autoreleasepool
- (void)doSomething {
NSMutableArray *collection = @[].mutableCopy;
for (int i = 0; i < 10e6; ++i) {
NSString *str = [NSString stringWithFormat:@"hi + %d", i];
[collection addObject:str];
}
NSLog(@"finished!");
}
不使用性能如下如所示:

不使用
- 使用autoreleasepool
- (void)doSomething {
NSMutableArray *collection = @[].mutableCopy;
for (int i = 0; i < 10e6; ++i) {
@autoreleasepool {
NSString *str = [NSString stringWithFormat:@"hi + %d", i];
[collection addObject:str];
}
}
NSLog(@"finished!");
}
使用效果如下圖所示:

使用autoreleasepool
綜上,當需要在程序中創(chuàng)建大量的臨時變量時(大量也可指數(shù)量多,不確定,比如從數(shù)據(jù)庫中讀取數(shù)據(jù)時),很容易使內(nèi)存產(chǎn)生峰值又回到內(nèi)存低谷,這樣對程序的性能會產(chǎn)生很大影響,而使用自動釋放池后,峰值明顯有所下降。
原因:由于在mian函數(shù)中已經(jīng)為我們添加了自動釋放池,如下所示:
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
而當autoreleasepool的右括號結(jié)束后,會對整個autoreleasepool做一次傾倒。但是這會使其中局部產(chǎn)生的大量零時變量無法及時釋放,直到for循環(huán)結(jié)束后抵達main中autoreleasepool的右括號位置才能釋放。這樣會在局部位置發(fā)生內(nèi)存峰值。
官方提出的解決方案是,在大量產(chǎn)生局部變量的位置用autoreleasepool代碼塊進行包裝。比如for循環(huán)中要執(zhí)行的語句,這樣每次for循環(huán)結(jié)束后就會及時收回臨時變量占用的內(nèi)存空間。
思考:如何在指定的次數(shù)時,及時釋放自動釋放池中的臨時變量
使用mrc下的特性
在編譯選項中,為MRC的程序添加-fno-objc-arc標記,表明在編譯時,該文件使用MRC編譯
如果要在MRC項目中添加ARC的文件,可以使用 -fobjc-arc 標記即可
這里的需求我們可以使用MRC時代的一個重量級的自動釋放池,通常用來創(chuàng)建偶爾需要釋放清空的池。
- (void)doSomething {
int count = 0;
NSMutableArray *collection = @[].mutableCopy;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (int i = 0; i < 10e6; ++i) {
NSString *str = [NSString stringWithFormat:@"hi + %d", i];
[collection addObject:str];
if (++count == 100) {
/** 每一百次傾倒一次池子 */
[pool drain];
count = 0;
}
}
/** 用來傾倒當i的個數(shù)不是100的倍數(shù)時,比如讀取數(shù)據(jù)庫數(shù)據(jù)時,數(shù)據(jù)總數(shù)為不確定值 */
[pool drain];
NSLog(@"finished!");
}