2010年10月5日火曜日

NSAutoreleasePool と UIImage

[前回] Cocoaの日々: NSAutoreleasePool を使ってメモリ解放

NSAutorelesaePool 調査中。今回は気になるところがあって UIImage を調べてみた。

検証コード


90〜100KB程度のJPEG画像を16枚用意して前回の様に NSAutoreleasePoolの効果を見る。

なお UIImage にはキャッシュを使う imageNamed: があるので、これとキャッシュを使わない imageWithContentsOfFile: の2つについてそれぞれ調べる。

コードはこんな感じ。
- (void)test2
{ 
 u_int prev_rss = [self currentRegidentSize];
 for (int i=1; i <= 16; i++) {
  
  NSString* filename = [NSString stringWithFormat:@"image%02d.jpg", i];


#ifdef USE_POOL
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
#endif
  
#ifdef USE_CACHE
  [UIImage imageNamed:filename];
#else
  NSString* filepath = [NSString stringWithFormat:@"%@/%@",
     [[NSBundle mainBundle] resourcePath], filename];
  UIImage* image = [UIImage imageWithContentsOfFile:filepath];
  
#endif
  
#ifdef USE_POOL
#ifdef USE_DRAIN
  [pool drain];
#else
  [pool release];
#endif
#endif
  u_int rss = [self currentRegidentSize];
  NSLog(@"%@ | RSS: %0.1f KB => %0.1f KB [%+0.1fKB]",
    filename, prev_rss/1024.0,rss/1024.0, (int)(rss-prev_rss)/1024.0);
  prev_rss = rss;
 }
 NSLog(@"end");
 // NSLog(@"%@", [NSAutoreleasePool showPools]);
}


結果


NSAutoreleasePool あり/なしと、imageNamed: / imageWithContentsOfFile: の組み合わせ計4種類の結果。

NSAutoreleasePoolなし / imageNamed:

image01.jpg | RSS: 11792.0 KB => 11936.0 KB [+144.0KB]
image02.jpg | RSS: 11936.0 KB => 12252.0 KB [+316.0KB]
image03.jpg | RSS: 12252.0 KB => 12272.0 KB [+20.0KB]
image04.jpg | RSS: 12272.0 KB => 12288.0 KB [+16.0KB]
image05.jpg | RSS: 12288.0 KB => 12308.0 KB [+20.0KB]
image06.jpg | RSS: 12308.0 KB => 12328.0 KB [+20.0KB]
image07.jpg | RSS: 12328.0 KB => 12340.0 KB [+12.0KB]
image08.jpg | RSS: 12340.0 KB => 12356.0 KB [+16.0KB]
image09.jpg | RSS: 12356.0 KB => 12372.0 KB [+16.0KB]
image10.jpg | RSS: 12372.0 KB => 12392.0 KB [+20.0KB]
image11.jpg | RSS: 12392.0 KB => 12408.0 KB [+16.0KB]
image12.jpg | RSS: 12408.0 KB => 12424.0 KB [+16.0KB]
image13.jpg | RSS: 12424.0 KB => 12440.0 KB [+16.0KB]
image14.jpg | RSS: 12440.0 KB => 12456.0 KB [+16.0KB]
image15.jpg | RSS: 12456.0 KB => 12484.0 KB [+28.0KB]
image16.jpg | RSS: 12484.0 KB => 12504.0 KB [+20.0KB]
end

NSAutoreleasePoolなし / imageWithContentsOfFile:

image01.jpg | RSS: 11800.0 KB => 11916.0 KB [+116.0KB]
image02.jpg | RSS: 11916.0 KB => 12232.0 KB [+316.0KB]
image03.jpg | RSS: 12232.0 KB => 12248.0 KB [+16.0KB]
image04.jpg | RSS: 12248.0 KB => 12264.0 KB [+16.0KB]
image05.jpg | RSS: 12264.0 KB => 12280.0 KB [+16.0KB]
image06.jpg | RSS: 12280.0 KB => 12296.0 KB [+16.0KB]
image07.jpg | RSS: 12296.0 KB => 12312.0 KB [+16.0KB]
image08.jpg | RSS: 12312.0 KB => 12328.0 KB [+16.0KB]
image09.jpg | RSS: 12328.0 KB => 12340.0 KB [+12.0KB]
image10.jpg | RSS: 12340.0 KB => 12360.0 KB [+20.0KB]
image11.jpg | RSS: 12360.0 KB => 12372.0 KB [+12.0KB]
image12.jpg | RSS: 12372.0 KB => 12388.0 KB [+16.0KB]
image13.jpg | RSS: 12388.0 KB => 12404.0 KB [+16.0KB]
image14.jpg | RSS: 12404.0 KB => 12420.0 KB [+16.0KB]
image15.jpg | RSS: 12420.0 KB => 12424.0 KB [+4.0KB]
image16.jpg | RSS: 12424.0 KB => 12436.0 KB [+12.0KB]
end

NSAutoreleasePoolあり [release] / imageNamed:

image01.jpg | RSS: 11804.0 KB => 11952.0 KB [+148.0KB]
image02.jpg | RSS: 11952.0 KB => 12280.0 KB [+328.0KB]
image03.jpg | RSS: 12280.0 KB => 12296.0 KB [+16.0KB]
image04.jpg | RSS: 12296.0 KB => 12308.0 KB [+12.0KB]
image05.jpg | RSS: 12308.0 KB => 12328.0 KB [+20.0KB]
image06.jpg | RSS: 12328.0 KB => 12332.0 KB [+4.0KB]
image07.jpg | RSS: 12332.0 KB => 12340.0 KB [+8.0KB]
image08.jpg | RSS: 12340.0 KB => 12348.0 KB [+8.0KB]
image09.jpg | RSS: 12348.0 KB => 12360.0 KB [+12.0KB]
image10.jpg | RSS: 12360.0 KB => 12376.0 KB [+16.0KB]
image11.jpg | RSS: 12376.0 KB => 12392.0 KB [+16.0KB]
image12.jpg | RSS: 12392.0 KB => 12408.0 KB [+16.0KB]
image13.jpg | RSS: 12408.0 KB => 12424.0 KB [+16.0KB]
image14.jpg | RSS: 12424.0 KB => 12440.0 KB [+16.0KB]
image15.jpg | RSS: 12440.0 KB => 12460.0 KB [+20.0KB]
image16.jpg | RSS: 12460.0 KB => 12472.0 KB [+12.0KB]
end

NSAutoreleasePoolあり [release] / imageWithContentsOfFile:

image01.jpg | RSS: 11784.0 KB => 11912.0 KB [+128.0KB]
image02.jpg | RSS: 11912.0 KB => 12224.0 KB [+312.0KB]
image03.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image04.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image05.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image06.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image07.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image08.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image09.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image10.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image11.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image12.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image13.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image14.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image15.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
image16.jpg | RSS: 12224.0 KB => 12224.0 KB [+0.0KB]
end

キャッシュを使わない imageWithContentsOfFile: は前回同様、NSAutoreleasePoolの有無でメモリの解放が状況が変わる。一方、キャッシュが使われる imageNamed: の場合は NSAutoreleasePoolを使用して解放を行ってもメモリの利用量は変わらない。つまりデータがキャッシュに残っている。


ソースコード


GitHubからどうぞ。
xcatsanのプロフィール - GitHub


- - - - -

-[NSAutoreleasePool drain] のケースも確認したが違いはなし。別件で解放に違いが出ていた原因はなんだったのだろうか。

2 件のコメント:

  1. 記事の趣旨とはずれますが、iOS4.0/4.1では*WithContentsOfFile系のメソッドだと、Retinaディスプレイ対応リソース(*@2x)への自動変換が行われないそうです。

    裏が取れていない情報ですみませんが、同OSを相手にする場合、必然的にimageNamed:にせざるを得ないようです。

    返信削除
  2. KatokichiSoft さん、こんばんは。

    Retina対応を考えると指摘の通りのようですね。imageNamed: のキャッシュは便利な反面、メモリも食うのでキャッシュ容量やクリアのコントロールできると一番いいのですが。。

    毎回情報ありがとうございます。

    返信削除