メモリ管理と割り当てをテストするために、単純なシングルビューアプリケーションを作成しviewDidAppear
、で、多くのオブジェクトを含む長いループを作成するために、次のように作成しました。
- (void) viewDidAppear:(BOOL)animated
{
NSDate * time = [NSDate date];
[super viewDidAppear:animated];
for (int i = 0; i < 20003; i++)
{
NSString * testString = [[NSString alloc] initWithString:@"This is a test string"];
NSMutableArray * itemsArray = [[NSMutableArray alloc] init];
for (int j = 0; j < 1000; j++)
{
[itemsArray addObject:testString];
}
if ((i % 1000) == 0)
{
NSLog(@"called %d", i);
}
}
NSDate * time2 = [NSDate date];
NSTimeInterval interval = [time2 timeIntervalSinceDate:time];
[label2 setText:[NSString stringWithFormat:@"time interval: %f", interval]];
}
予想どおり、メモリリークのプロファイリング中に、メモリリークが発生し、260 MBを超える割り当てが発生しました。スクリーンショット:
しかし、このドキュメントに従うとき、私はコードを次のように変更しました:
- (void) viewDidAppear:(BOOL)animated
{
NSDate * time = [NSDate date];
[super viewDidAppear:animated];
for (int i = 0; i < 20003; i++)
{
@autoreleasepool
{
NSString * testString = [NSString stringWithFormat:@"%@", @"This is a test string"];
NSMutableArray * itemsArray = [[NSMutableArray alloc] init];
for (int j = 0; j < 1000; j++)
{
[itemsArray addObject:testString];
}
[itemsArray release];
itemsArray = nil;
if ((i % 1000) == 0)
{
NSLog(@"called %d", i);
}
}
}
NSDate * time2 = [NSDate date];
NSTimeInterval interval = [time2 timeIntervalSinceDate:time];
[label2 setText:[NSString stringWithFormat:@"time interval: %f", interval]];
}
割り当て量に違いはありませんでしたが、メモリリークはなく、実行時間は2秒未満から約80秒に大幅に増加しました。
そして、リリースを使用した後も、変更はありませんでした。コード:
- (void) viewDidAppear:(BOOL)animated
{
NSDate * time = [NSDate date];
[super viewDidAppear:animated];
for (int i = 0; i < 20003; i++)
{
NSString * testString = [[NSString alloc] initWithString:@"This is a test string"];
NSMutableArray * itemsArray = [[NSMutableArray alloc] init];
for (int j = 0; j < 1000; j++)
{
[itemsArray addObject:testString];
}
[testString release];
testString = nil;
[itemsArray release];
itemsArray = nil;
if ((i % 1000) == 0)
{
NSLog(@"called %d", i);
}
}
NSDate * time2 = [NSDate date];
NSTimeInterval interval = [time2 timeIntervalSinceDate:time];
[label2 setText:[NSString stringWithFormat:@"time interval: %f", interval]];
}
そしてスクリーンショット:
また、MutableArrayを明示的に(を使用して[itemsArray release]
)空にしても、変化は見られませんでした。
私の質問は次のとおりです。
3つのケースで割り当てられたメモリの合計が変わらないのはなぜですか(2番目と3番目のケースではメモリリークがないにもかかわらず)、大きな割り当ての場合にそれを減らす方法はありますか?障害はどこにあり、消費されるメモリを減らす方法は?
次に、適切なツールを使用して適切な数値を読み取っていますか(Profiler Instrumentsのメモリリークを使用し、すべての割り当てを参照し、割り当ての寿命において、作成されたままの状態が選択されています)、正しい方法で実行していますか?つまり、これは現在消費されているメモリの量ですか、それともアプリケーションの起動以降に消費されたメモリの合計ですか?
1番目と3番目のケースではなく、2番目のケースでループの実行時間が大幅に増加したのはなぜですか?
xCode 4.5を使用し、ARCもStoryBoardも使用せず、すべてのテストはシミュレーターで実行されました。