7

我上具有使用Web服務和核心數據在一個緊密的循環同步過程中的iPad應用工作。根據Apple's Recomendation我分配減少內存佔用和週期性漏極的NSAutoreleasePool。這目前效果很好,目前的應用程序沒有內存問題。但是,我打算轉移到ARC,因爲NSAutoreleasePool不再有效,並希望保持這種相同的性能。我創建了幾個例子和定時他們我想知道什麼是最好的方法,使用ARC,以acheive同類性能和維護代碼的可讀性降低峯值內存使用@autoreleasepool

出於測試目的,我想出了3個場景,每個創建使用1和10,000,000之間的數字的字符串。我跑了每個示例3次,以確定他們是否使用與蘋果LLVM編譯器3.0在Mac 64位應用程序所用的時間(W/O GDB -O0)和XCode的4.2。我還通過儀器運行每個示例來大致瞭解記憶峯值。

以下每個都包含在下面的代碼塊中的例子:

int main (int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     NSDate *now = [NSDate date]; 

     //Code Example ... 

     NSTimeInterval interval = [now timeIntervalSinceNow]; 
     printf("Duration: %f\n", interval); 
    } 
} 

NSAutoreleasePool批次[原件預ARC](峯值記憶:〜116 KB)

static const NSUInteger BATCH_SIZE = 1500; 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++) 
    { 
     NSString *text = [NSString stringWithFormat:@"%u", count + 1U]; 
     [text class]; 

     if((count + 1) % BATCH_SIZE == 0) 
     { 
      [pool drain]; 
      pool = [[NSAutoreleasePool alloc] init]; 
     } 
    } 
    [pool drain]; 

運行時間:
10.928158
10.912849
11.084716


外@autoreleasepool(峯值存儲器:〜382 MB)

@autoreleasepool { 
     for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++) 
     { 
      NSString *text = [NSString stringWithFormat:@"%u", count + 1U]; 
      [text class]; 
     } 
    } 

運行時間:
11.489350
11.310462
11.344662


內@autoreleasepool(峯值記憶:〜61.2KB)

for(uint32_t count = 0; count < MAX_ALLOCATIONS; count++) 
    { 
     @autoreleasepool { 
      NSString *text = [NSString stringWithFormat:@"%u", count + 1U]; 
      [text class]; 
     } 
    } 

運行時間:
14.031112
14.284014
14。099625


@autoreleasepool瓦特/ GOTO(峯值存儲器:〜115KB)

static const NSUInteger BATCH_SIZE = 1500; 
    uint32_t count = 0; 

    next_batch: 
    @autoreleasepool { 
     for(;count < MAX_ALLOCATIONS; count++) 
     { 
      NSString *text = [NSString stringWithFormat:@"%u", count + 1U]; 
      [text class]; 
      if((count + 1) % BATCH_SIZE == 0) 
      { 
       count++; //Increment count manually 
       goto next_batch; 
      } 
     } 
    } 

運行時間:
10.908756
10.960189
11.018382

goto聲明提供最接近的性能,但它採用的是goto。有什麼想法嗎?

更新:

注:goto聲明是在documentation表示不會泄漏內存的@autoreleasepool一個正常的退出。

在進入時,會推送自動釋放池。在正常退出(中斷, 返回,轉到,通過,等等)自動釋放池被彈出。 爲了與現有代碼兼容,如果退出是由於例外造成的,則 自動釋放池不會彈出。

+1

使用優化。這對ARC代碼來說非常重要。 – 2012-03-12 21:58:20

+0

因此'goto'肯定不是,我不知道,導致內存泄漏?其他一切都合情合理:減少排水速度更快。無論如何,我只能評論可讀性:在任何你游泳池都很好。那個goto需要一個黃色的粘滯便箋。 – 2012-03-12 21:58:42

+0

goto似乎沒有泄漏任何內存。看起來像我期望的那樣排除了autorelease池的範圍,但我不是ARC的專家(還),並且不想依賴UB。 – Joe 2012-03-12 22:07:06

回答

9

下應達到同樣的事情goto答案沒有goto

for (NSUInteger count = 0; count < MAX_ALLOCATIONS;) 
{ 
    @autoreleasepool 
    { 
     for (NSUInteger j = 0; j < BATCH_SIZE && count < MAX_ALLOCATIONS; j++, count++) 
     { 
      NSString *text = [NSString stringWithFormat:@"%u", count + 1U]; 
      [text class]; 
     } 
    } 
} 
+0

謝謝,漫長的一天,簡單的答案:)。 – Joe 2012-03-13 00:07:51

+1

這應該是更多投票,因爲它正是解決方案,以獲得與舊的'NSAutoreleasePool'手動排水一樣的行爲! – mattjgalloway 2012-03-26 16:55:10

2

注意,ARC使得未在-O0啓用顯著優化。如果要在ARC下測量性能,那麼必須在啓用優化的情況下測試。否則,您將根據ARC的「樸素模式」測量您手動調整的保留/釋放位置。

通過優化再次運行您的測試並查看會發生什麼。

更新:我很好奇,所以我自己跑了。這些是發佈模式(-Os)的運行時結果,具有7,000,000個分配。

arc-perf[43645:f803] outer: 8.1259 
arc-perf[43645:f803] outer: 8.2089 
arc-perf[43645:f803] outer: 9.1104 

arc-perf[43645:f803] inner: 8.4817 
arc-perf[43645:f803] inner: 8.3687 
arc-perf[43645:f803] inner: 8.5470 

arc-perf[43645:f803] withGoto: 7.6133 
arc-perf[43645:f803] withGoto: 7.7465 
arc-perf[43645:f803] withGoto: 7.7007 

arc-perf[43645:f803] non-ARC: 7.3443 
arc-perf[43645:f803] non-ARC: 7.3188 
arc-perf[43645:f803] non-ARC: 7.3098 

和Memory峯(僅10萬個撥款運行,因爲儀器正在採取永遠):

Outer: 2.55 MB 
Inner: 723 KB 
withGoto: ~747 KB 
Non-ARC: ~748 KB 

這些結果讓我感到驚訝了一點。那麼,記憶峯值結果不會;這正是你所期望的。但是即使啓用了優化,innerwithGoto之間的運行時間差也比我預期的要高。

當然,這是一種病態的微觀測試,很難模擬任何應用程序的真實世界的性能。這裏要說的是ARC可能確實存在一些開銷,但在做出假設之前,您應該始終測量您的實際應用。

(另外,我使用嵌套的for循環測試@ ipmcc的答案,它的表現幾乎完全一樣的goto版本)。

+0

謝謝,感謝小費。沒有意識到採取了額外的步驟,但從那時起就是絕對的。是否有類似於http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html的優化指南?不期望找到確切的標誌,但更多地沿着什麼樣的優化可能發生的路線。我發現了一些有用的屬性項[這裏](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#optimization),但它看起來並不像編譯器優化所依賴的。 – Joe 2012-03-13 18:01:57

+0

我添加了一些真實世界的測試,啓用優化。 – 2012-03-13 21:02:50

+0

感謝您的幫助,通過優化檢查統計信息。這對於決定將來使用哪種方法用於各種目的很有用(除了'goto'感謝ipmcc的回答以外)。希望有更多的人能夠通過並積極參與。 – Joe 2012-03-13 21:23:10