Высокое использование памяти при импорте CoreData - PullRequest
3 голосов
/ 28 марта 2011

Я пытаюсь выполнить довольно большой импорт CoreData (около 25 000 строк), сохраняя при этом довольно низкий объем занимаемой памяти. Я прочитал документацию, касающуюся эффективного импорта данных, и постарался реализовать все, что там предлагалось (включая установку таких вещей, как undoManager моего MOC, равным nil).

К сожалению, использование моего приложения по-прежнему увеличивается до 180 МБ при запуске приведенного ниже кода. После завершения приложение будет находиться на отметке 180 МБ независимо от окончательного запроса на утечку NSAutoreleasePool.

Запуск приложения через 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];
    }
}

1 Ответ

1 голос
/ 10 июня 2011

Вместо того, чтобы иметь дело с пулами автоматического выпуска, почему бы явно не управлять жизненным циклом ваших управляемых объектов, создавая их с помощью NSManagedObject s initWithEntity:insertIntoManagedObjectContext:? Вы можете безопасно освобождать их после изменения свойств объекта, поскольку контекст управляемого объекта сохраняет вновь вставленный объект - до тех пор, пока он не будет сохранен в постоянном хранилище.

Кроме того, я должен упомянуть пару проблем, которые я вижу с вашим кодом:

  1. Как уже упоминалось выше, вы не регистрируете ошибки из операции save:. Вы действительно должны - это может выделить некоторые (возможно, не связанные) проблемы.

  2. Если сохранение: успешно, вам действительно не нужно звонить reset. См. этот раздел в руководстве по основным данным.

...