3

メモリ フットプリントをかなり低く維持しながら、かなり大きな CoreData インポート (約 25,000 行) を実行しようとしています。データの効率的なインポートに関するドキュメントを読み、そこで提案されているすべてを実装するよう努めました (MOC の undoManager を nil に設定するなど)。

残念ながら、以下のコードを実行すると、アプリケーションのメモリ使用量は依然として約 180MB に達します。完了すると、最後の NSAutoreleasePool ドレイン コールに関係なく、アプリケーションは約 180MB マークに留まります。

Allocations を使用してアプリケーションを実行すると、メモリ使用量の 95% が私の[self.moc save:&error]呼び出しに起因することがわかります。ここで何が間違っていますか?

- (void)generateCache
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSUInteger count = 0, batchSize = 1000;

    // SNIP SNIP

    // Iterate over our directory structure
    for(NSString *item in directoryStructure)
    {
        NSDictionary *info = [fm attributesOfItemAtPath:item error:nil];

        FileRecord *record = (FileRecord *)[NSEntityDescription insertNewObjectForEntityForName:@"FileRecord" inManagedObjectContext:self.moc];
        record.size = [NSNumber numberWithUnsignedLongLong:[info fileSize]];
        record.path = item;

        count ++;
        if(count == batchSize)
        {
            NSError *error = nil;

            if([self.moc save:&error])
            {
                NSLog(@"MOC saved down and reset");
                [self.moc reset];
                [pool drain];

                pool = [[NSAutoreleasePool alloc] init];
                count = 0;
            }
        }
    }

    // Perform any necessary last minute MOC saves
    if (count != 0) {
        [self.moc save:nil];
        [self.moc reset];
    }

    // Drain our NSAutoreleasePool
    [pool drain];

    // Tell our main thread that we're done
    if ([self respondsToSelector:@selector(completedCache)]) 
    {
        [self performSelectorOnMainThread:@selector(completedCache) withObject:nil waitUntilDone:NO];
    }
}
4

1 に答える 1

1

自動解放プールを扱う代わりに、管理対象オブジェクトを で作成してライフサイクルを明示的に管理してみませんNSManagedObjectinitWithEntity:insertIntoManagedObjectContext:? 管理対象オブジェクト コンテキストは新しく挿入されたオブジェクトを永続ストアに保存されるまで保持するため、オブジェクトのプロパティを変更した後、それらを安全に解放できます。

また、あなたのコードで見られるいくつかの問題について言及する必要があります。

  1. 上記の誰かが言ったように、save:操作からのエラーをログに記録していません。あなたは本当にすべきです-それはいくつかの(おそらく無関係な)問題を浮き彫りにするかもしれません.

  2. save: が成功した場合、 を呼び出す必要はありませんreset。コア データ ガイドのこのセクションを参照してください。

于 2011-06-09T21:42:13.830 に答える