關于@autoreleasepool的性能測試及手動釋放自動釋放池

原文地址: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
使用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!");
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容