2010-10-01 2 views
4

У меня возникла проблема с CoreGraphics/CoreAnimation на iPhone. Чтобы лучше объяснить, как проблема проявляется, я проведу вас через свою текущую настройку и проиллюстрирую код, где это необходимо.Использование памяти CALayer для рисования - неявный кеш?

Я пытаюсь сделать кучу загруженных изображений в UIView «s CALayer, но всякий раз, когда изображение отображается, спайки использования памяти приложения и память не утилизированы всякий раз, когда изменения изображений.

Предварительная загрузка изображений осуществляется путем считывания их через объекты UIImage, превращая их в контекст растрового изображения и извлекая из этого контекста CGImageRef. Цель этого - распаковать и масштабировать изображения, чтобы эти операции не выполнялись при каждой ничьей. Аналогичную рекомендацию можно найти в Apple Q & A по этому вопросу (поиск CGContextDrawImage производительности, если вам интересно). Контекст настроен на 8 бит на компонент и предварительно умноженную альфу.

После того, как изображения распаковываются в растровые изображения, они сохраняются в NSArray и позже назначаются (не сохраняются) в подклассу UIView, который выполняет чертеж. Я пробовал различные подходы к фактическому рисованию изображений, и, безусловно, самый быстрый метод непосредственно устанавливает свойство CALayer . Другие методы, такие как drawLayer:inContext: и drawRect:, оказывают различное влияние на частоту кадров, но все они имеют одинаковое поведение памяти.

Проблема в том, что после изменения свойств, я вижу всплеск в памяти в Инструментах, и эта память не падает даже после того, как изображение больше не отображается. Объект Allocations остается постоянным, поэтому я предполагаю, что CoreAnimation создает неявный кеш для ускорения рисования. Однако, как я уже сказал, этот кеш не выпущен, когда это необходимо, и постепенное наращивание приводит к сбою всего за пару минут работы.

Свойство contents сохраняет объект, и я не могу его явно освободить, потому что я хочу, чтобы исходные изображения оставались в памяти на время выполнения приложения; Кроме того, высокий показатель удержания не учитывает всплески памяти, которые я вижу.

При рассмотрении стека я вижу, что CoreAnimation выполняет звонки на такие функции, как CA::Render::copy_image, что заставляет меня думать, что он дублирует содержимое слоя где-то вне досягаемости. Я полагаю, что для этого есть веская причина, но не знаю, как и когда очистить это в настоящее время ошибка остановки шоу.

Так может кто-нибудь с замысловатым знанием CA, пожалуйста, объясните мне, если я что-то делаю неправильно и как я могу обойти это поведение.

Спасибо.

+0

Что именно вы подразумеваете под «чтением их через объекты UIImage»? –

+0

Либо imageWithContentsOfFile: или imageWithData: – SuperNES

+0

Привет всем, Мне кажется, что вы, ребята, лучше понимаете CALayer, что я. У меня есть проблема с Callayer malloc, если кто-нибудь из вас может взглянуть, я был бы очень благодарен ... http://stackoverflow.com/questions/26715727/setneedsdisplay-drawrect-or-calayer-causing-dispatch- продолжение Alloc-с-он – Niall

ответ

2

Я делаю именно то, что вы описали - без изучения утечек. Возможно, это поможет, когда вы предоставите свой источник.

Однако, я проверяю, что CA выделяет системную память, которые не записаны в «Обвязке объектов», а в «Мониторинг активности» Instrument, соответственно, в «Мониторе памяти» Instrument, а именно «Physical Memory Free». «Physical Memory Free» уменьшается, когда изображение рисуется в неэкранном контексте, и оно также уменьшается при отображении этого изображения.

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

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

Если вы не предоставите свой источник, я бы заподозрил, что ваш счет за сохранение ваших CGImageRefs не сбалансирован - и, следовательно, они протекают. Обратите внимание, что CGImageRef не следует напрямую помещать в NSArray - они не ведут себя как объекты Objective-C (также как бесплатный мост для UIImage) - вам нужно явно вызвать CGImageRetain/CGImageRelease.

5

@CouchDeveloper - спасибо, что нашли время ответить.

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

Ваше мнение о распределении и использовании памяти является правильным. Память, на которую я смотрю, - это «реальная» (резидентная) память, используемая приложением в инструменте Monitor Monitor (Activity Monitor).

Я думаю, что я открыл причину для этих таинственных распределений памяти. Когда CoreAnimation сталкивается с изображением, которое не находится в собственном формате пикселей, оно копирует изображение в собственный буфер, и это похоже на использование, которое я вижу. Я считаю, что правильный формат - 32 бит, порядок байтов хоста, предварительно умноженный альфа-первый (битмап-информационные флаги kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host).

Чтобы узнать, какие экземпляры CGImageRef копируются и более подробно изучают внутренние работы фреймворка, вы можете использовать инструмент Core Animation на устройстве или указать несколько переменных окружения и запустить iPhone Simulator из командная строка. Список всех флагов можно найти here. В моем случае наиболее полезной комбинацией является CA_COLOR_COPY и CA_LOG_IMAGE_COPIES, что даст скопированные изображения голубые оверлеи и копии журналов в stderr.

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

Надеюсь, это может быть полезно для других, задающихся вопросом, откуда происходят их проблемы с памятью и производительностью!

1

Вы нашли решение для своей проблемы? У меня точно такая же проблема. Я использую 32-битные PNG-файлы, я думал, что этого будет достаточно. Я действительно убедился, что не использую ImageNamed, так как этот славится кешированием вещей.

Я использовал imageWithData и даже удостоверился, что у NSData initWithContentsOfFile была опция Nocache NSRead, чтобы предотвратить кеширование FS, но это ничего не изменило.

ОБНОВЛЕНИЕ: я нашел, что моя проблема. не удалил вид из своего супервизора (который не был показан), и, похоже, где-то поддерживался некоторый кеш ...

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

  • Нет связанных вопросов^_^