iPhone iOS6, как вернуть резидентную грязную память типа Image IO в ОС?

Я смотрю видео WWDC 2010, посвященное расширенному анализу памяти (сессия 311):

введите здесь описание изображения

Примерно в 45:00 инженер по производительности обсуждает, что делать с «резидентной грязной памятью», которую ваше приложение загрузило в ОЗУ. Инженер предполагает, что в ответ на предупреждения памяти ваше приложение должно очищать это. Инженер вставляет метод "flush" своего пользовательского класса в didReceiveMemoryWarning, и все в порядке, но код на самом деле не предлагает никаких примеров того, КАК освобождается память.

У меня есть вопрос: как очистить большие куски грязной памяти, используемые "Image IO"?:

Вот около 74 МБ памяти, которые просто лежат грязными (уже почти 6 минут), ожидая, пока кто-нибудь вернет их в iOS6. С ним ничего не происходит. Так как оно не проходит само по себе, мне нужно знать, как вернуть его на iOS.

введите здесь описание изображения

Эти блоки, по-видимому, происходят из кода, подобного этому, и (возможно, других операций, связанных с изображением).

 UIImage *screenshot = nil;

    @autoreleasepool {

        if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
            UIGraphicsBeginImageContextWithOptions(iPhoneRetinaIconSize, NO, [UIScreen mainScreen].scale);

        else
            UIGraphicsBeginImageContext(iPhoneRetinaIconSize);


        [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
        screenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

    }

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

Для грязной памяти, связанной с веб-просмотром, я обнаружил, что это может работать:

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    [[NSURLCache sharedURLCache] setDiskCapacity:0];
    [[NSURLCache sharedURLCache] setMemoryCapacity:0];
    // Dispose of any resources that can be recreated.
}

Есть ли эквивалент для UIImage, CALayer или UIGraphics?


person Alex Stone    schedule 03.04.2013    source источник
comment
Насколько я понимаю, UIImage делает это автоматически, но только для изображений, загруженных с помощью imageNamed, поэтому вы должны обязательно использовать этот вариант при загрузке из вашего пакета.   -  person Hot Licks    schedule 03.04.2013


Ответы (1)


Я далеко не эксперт в этих вопросах, но, основываясь на тестах, которые я провел с предоставленным вами кодом, я бы сказал, что вам просто нужно выпустить UIImage, созданные в этих блоках кода.

Насколько я понимаю, фрагменты памяти, помеченные Image IO или GC raster data, на самом деле являются просто базовыми данными ваших изображений (UIImage является оболочкой UIKit поверх них). Итак, чтобы освободить память, освободите образ.

Я проверил это, создав кучу UIImage с помощью вашего кода, имитируя предупреждение памяти, которое освобождало все созданные изображения:

Огромные 1,5 ГБ компьютерных данных
Все пропало!

Изображения говорят сами за себя. Освобождение моих UIImages (в ~00:08) удалило большой кусок GC raster data из резидентной памяти.

Поскольку полное удаление изображения из вашего пользовательского интерфейса может быть не лучшим решением для пользователей, возможно, вы могли бы попытаться уменьшить размер самых больших изображений при получении предупреждения о памяти, более низкое разрешение приводит к меньшему объему памяти. Другая идея (опять же, это зависит от того, для чего используются ваши изображения) может состоять в том, чтобы выгружать изображения на диск и загружать их позже, когда это необходимо.

Надеюсь, это поможет.

person Guillaume Algis    schedule 16.06.2013
comment
У меня это произошло в ARC, и мне еще раз напомнили, что API-интерфейсы C, такие как Core Graphics, не используют ARC, и мы должны выпускать объекты CG вручную. - person Enrico Susatyo; 17.06.2013