2013-08-11 3 views
2

Advanced Memory Management Programming Guide говорит о @autoreleasepool:Нужна помощь в отношении @autoreleasepool

Использование местных Autorelease Бассейн блоков для снижения пиковых памяти Footprint

Многие программы создают временные объекты, которые autoreleased. Эти объекты добавляют к области памяти программы до конца блока . Во многих ситуациях, позволяя временным объектам накапливать до конца текущей итерации цикла событий, не приводит к избыточным накладным расходам ; в некоторых ситуациях, однако, вы можете создать большое количество временных объектов, которые существенно добавляются в память , и что вы хотите избавиться быстрее. В последних вы можете создать свой собственный блок пула авторезистов. На конце блока временные объекты освобождаются, что обычно приводит к их освобождению, тем самым уменьшая память программы .

В следующем примере показано, как вы можете использовать локальный пул автозапуска в цикле for.

NSArray *urls = <# An array of file URLs #>; 
for (NSURL *url in urls) { 

    @autoreleasepool { 
     NSError *error; 
     NSString *fileContents = [NSString stringWithContentsOfURL:url 
             encoding:NSUTF8StringEncoding error:&error]; 
     /* Process the string, creating and autoreleasing more objects. */ 
    } 
} 

Может ли этот код также может быть написана без autoreleasepool и эффективно управлять?

как создание property of fileContents и установка nil после обработки.

self.filecontents = nil; 
+0

Этого код может быть написан без ARP, как существует ARC в прошивке в настоящее время. – Ashwani

+2

@Ashwin: Насколько я понимаю, пулы автозапуска не зависят от ручного и автоматического подсчета ссылок. Даже с MRP код может быть написан без ARP (просто замените 'fileContents = nil' на' [fileContents release] 'в моем предложенном ниже ответе). –

+2

@Ashwin Это просто неправильно. Формат блока 'autorelease' был введен с ARC. Автореализованные объекты в цикле не будут выпущены до тех пор, пока цикл выполнения не удастся выполнить следующую итерацию (поскольку 'UIKit' запускает каждое событие в блоке' autoreleasepool'), если только не используется 'autoreleasepool'. – danielbeard

ответ

5

Проблема заключается в том, что stringWithContentsOfURL может вернуть autoreleased объект. Но вы могли бы использовать initWithContentsOfURL вместо:

NSArray *urls = <# An array of file URLs #>; 
for (NSURL *url in urls) { 
    NSError *error; 
    NSString *fileContents = [[NSString alloc] initWithContentsOfURL:url 
            encoding:NSUTF8StringEncoding error:&error]; 
    /* Process the string ... */ 
    fileContents = nil; 
} 

init... методы возвращают (+1) сохранила объект и не autoreleased объекта, поэтому fileContents = nil освобождает объект и разрушают его (если нет других сильных ссылок Это).

Конечно, это помогло бы, только если «код строковой обработки» не производит других объектов с автореализацией. (Также error, если установлено, был бы autoreleased объекта.)

(На самом деле это не «гарантировано», что stringWithContentsOfURL возвращает autoreleased объекта. Особенно в режиме выпуска, АРК компилятор удаляет много ненужных сохранить/autorelease/.

Я не знаю, является ли создание местного пула авторезистов дорогостоящей операцией или нет (предположим, что нет). Если вы обрабатываете много объектов, и вы не знаете , независимо от того, созданы ли автореализованные объекты или нет, может быть разумно просто использовать локальный пул авторефератов и «не заботьтесь об этом». Профилирование с помощью «Инструменты» также может дать более глубокое понимание.

Для получения дополнительной информации см. «Сохраненные значения возврата» и «Недопустимые значения возврата» в Clang ARC documentation.

+0

@ S.J мартин правый. Также я бы предпочел '@ autoreleasepool', так как в коде фреймворка также используется много автореализованных объектов (только предположение). Использование autorelease могло бы отбросить эти объекты, несмотря на то, что вы были автореализованными объектами. –

1

Нет никакой разницы в назначении сильного свойства, а затем при его отсутствии и назначении сильной локальной переменной и ее выходе из области видимости. Основная проблема заключается в том, что объект, назначенный fileContents, помещается в пул авторезистов, который не будет сливаться по крайней мере до тех пор, пока цикл for не завершит итерацию всех URL-адресов. Помещение тела цикла внутри блока @autoreleasepool приводит к тому, что fileContents должен быть автореализован с каждой итерацией цикла.

0

Похоже на то, что на поверхности, но любой метод какао, который вы вызываете, может потенциально создать автореализованный объект за кулисами ... поскольку вы можете видеть, выполняете ли вы такую ​​же операцию в другом потоке без пула автозапуска.

разумно добавить отдельный бассейн, если у вас длинная беговая петля.

есть также модель, которая используется, чтобы быть более популярными, что идет как:

NSAutoreleasePool * pool = [NSAutoreleasePool new]; 
for (int i =0;i>3009;i++){ 
    //do stuff; 
    if(!(i%100)) 
    { 
     [pool drain],pool = [NSAutoreleasePool new];} 
} 
[pool drain]; 
+0

Блоки '@ autoreleasepool' более эффективны, чем напрямую использовать объекты NSAutoReleasePool. Дополнительную информацию см. В документации: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html. – danielbeard

Смежные вопросы