そういえばNSUserDefaultsのメモリの扱い全然知らないなと思って、ネットで調べてみても出なかったので 自分で検証して見ました。 結果、NSUserDefaultsの使用容量によってはアプリがすごい重くなったり、下手をすれば起動自体しなくなることがある!!ってことがわかりました! 結構驚きです。
いつデータはロードされるのか
NSUserDefaultsのメモリ関係で一番気になるのはいつデータがロードされて、いつ解放されるかです。 それを調べるために次のような手順のソースでメモリを監視して見ました。
- standardUserDefaultsを呼び出すだけ
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- 値1個を保存
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; id value = [userDefaults valueForKey:@"key"];
- すでに保存されている値1個を取り出す
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; id value = [userDefaults valueForKey:@"key"];
- 値1000個を保存
NSUserDefaults \*userDefaults = [NSUserDefaults standardUserDefaults]; for(int i = 0; i < MAX_KEY; i++){ NSAutoreleasePool \*pool = [[NSAutoreleasePool alloc] init]; NSString \*value = [NSString stringWithFormat:@"value No.%d",i]; NSString \*key = [NSString stringWithFormat:@"%d",i]; [userDefaults setValue:data forKey:key]; [pool release]; }
- すでに保存されている値10000個を取り出す
NSUserDefaults \*userDefaults = [NSUserDefaults standardUserDefaults]; for(int i = 0; i < MAX_KEY; i++){ NSAutoreleasePool \*pool = [[NSAutoreleasePool alloc] init]; NSString \*key = [NSString stringWithFormat:@"%d",i]; NSString \*value = [userDefaults valueForKey:key]; [pool release]; }
(値はすべて英数10文字です。) さて、その結果は次のようになりました。
コード前後での
メモリ使用量の増加分
standardUserDefaultsを呼び出すだけ
5KB
値1個を保存
5KB
値1個を取り出す
3KB
値1000個を保存
85KB
値1000個を取り出す
5KB
保存時にはそれなりにメモリを食うけれども、読み込み時にはメモリを全然使いませんでした。 これは、
- 起動→保存→読み込み
- 起動→読み込み
のどちらの時も同じでした。 また、保存されているデータがどんなに大きくなってもstandardUserDefaultsを呼び出すだけではメモリをほとんど消費しません。 さて、データはどのタイミングでロードされてるんでしょう・・・・?
データロードのタイミング
色々試していて分かった結論を言うとデータはアプリ起動時に勝手に読み込まれます データの数を変えながら試してみると、起動時のメモリ消費量がNSUserDefaultsの容量に応じて増えてました。 NSUserDefaultsのデータは すべてアプリ起動時に全て読み込まれるようです。
NSUserDefaultsに登録したデータ数
アプリ起動直後のメモリ使用量
0
600Kb
1000個
670KB
2000個
770KB
10000個
3300KB
また、一度ロードされたデータはいつまでも解放されないようです。 これはシングルトンの性質上仕方ないかなと思います。
NSUserDefaultsが起動時に全てロードするのは結構危険です。 NSUserDefualtsにデータを保存しすぎると、アプリが使えるメモリが起動時からずっと圧迫されてしまうのです。 仮にアプリが10MBまでしかメモリをつかえないとしたとき NSUserDefaultsで6MBのデータを保存してしまったら アプリはのこり4Mbのメモリですべての動作を行わないといけなくなるのです。 NSUserDefaultsに大量のデータを入れると全体的にアプリが重くなることもありえますので、扱いには注意が必要そうです。 ちなみに、色々試してデータを沢山入れているとアプリが起動しなくなることもありました。 おそらく起動に必要なメモリすらも確保出来なかったんだと思います・・・・。