IOSDEV Telegram 537
Почему ваша картинка размером в 2 мегабайта может отъедать 80 мб памяти? Сейчас разберёмся.
Или как пофиксить одну из причин out of memory exception

На собеседованиях часто просят отобразить ленту из картинок, взятых откуда-нибудь из стороннего ресурса, гугла, например, условного unsplash или откуда-нибудь ещё. Скорее всего, и у инженеров на боевых проектах рано или поздно может возникнуть подобная задача.

Одна из потенциальных сложностей, с которой можно столкнуться при такой задаче — out of memory exception. Так в чём же дело?

Использование памяти нашим приложением резко возрастает, когда мы начинаем показывать HD-изображения на экране (даже одно уже может внести существенный импакт для увеличения используемой памяти).

Главное, что нужно запомнить, использование памяти ≠ размеру файла. И вот почему.

Использование памяти связано с размерами изображения, а не с размером файла (Session 416, WWDC 2018).

Всё дело в том, что для отображения изображения на экране, iOS сначала необходимо декодировать и распаковать изображение. Обычно 1 пиксель декодированного изображения занимает 4 байта памяти — 1 байт для красного, 1 байт для зеленого, 1 байт для синего и 1 байт для альфа-канала (да-да, тот самый RGB с альфой). Например:

(3648 * 5472) * 4 bytes ≈ 80MB

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

Что со всем этим делать?

Разработчики в этой статье пробовали менять масштаб и перерисовать изображение, но это не помогло. Это связано с тем, что операции для изменения размера для UIImage дороги. В процессе изменения размера iOS по-прежнему будет декодировать и распаковывать исходное изображение, вызывая нежелательный скачок памяти.

Одно из решений, которым делятся инженеры Apple — юзать даунсэмплинг.

Мы можем использовать ImageIO для изменения размера изображения перед его отображением на экране. По факту, для нас это выльется только в стоимости ресайзинга исходной картинки. Вот здесь можно чекнуть сниппет.

Флаги, которые можно использовать

1️⃣ kCGImageSourceShouldCache — когда для этого флага установлено значение false, мы сообщаем основному фреймворку, что нам нужно только создать ссылку на источник изображения и не хотим декодировать изображение сразу при создании объекта CGImageSource.

В ситуации, когда у вас нет доступа к пути к источнику изображения, вы можете создать объект CGImageSource, используя инициализатор CGImageSourceCreateWithData().

2️⃣ kCGImageSourceShouldCacheImmediately — этот флаг указывает, что декодировать изображение нужно именно в тот момент, когда мы запускаем процесс понижения дискретизации.

3️⃣ kCGImageSourceCreateThumbnailWithTransform — установка этого флага в значение true очень важно для сохранения исходной ориентации.

Подводные камни (а как же без них)

Имейте в виду, что даунсэмплинг — это процесс, который потребляет ресурсы процессора. Таким образом, по-прежнему предпочтительнее использовать правильно масштабированный источник изображения, а не понижать дискретизацию HD-изображения. Другими словами, вы должны использовать даунсэмплинг только тогда, когда вам нужно отобразить изображение, размер которого намного превышает требуемый размер на экране.

Важные моменты

Помните, что память — это конечный и общий ресурс.

Используйте встроенный в Xcode мониторинг.

Позвольте iOS выбрать ваши форматы изображений, когда это возможно.

Используйте ImageIO для понижения разрешения изображений (помните про подводные камни).

Выгружайте крупные ресурсы, которые находятся за пределами экрана.

Не игнорируйте графики памяти (memory graphs), чтобы лучше понять, что происходит.

Что почитать ещё?

📖 Deep Dive into iOS Memory.
📖 Reducing Memory Footprint When Using UIImage.
📺 Session 416, WWDC 2018.
🔗 https://developer.apple.com/documentation/imageio/cgimagesource.

@iOS Dev — отвечаем на вопросы.
🔥36👍13🏆62👏1



tgoop.com/iosdev/537
Create:
Last Update:

Почему ваша картинка размером в 2 мегабайта может отъедать 80 мб памяти? Сейчас разберёмся.
Или как пофиксить одну из причин out of memory exception

На собеседованиях часто просят отобразить ленту из картинок, взятых откуда-нибудь из стороннего ресурса, гугла, например, условного unsplash или откуда-нибудь ещё. Скорее всего, и у инженеров на боевых проектах рано или поздно может возникнуть подобная задача.

Одна из потенциальных сложностей, с которой можно столкнуться при такой задаче — out of memory exception. Так в чём же дело?

Использование памяти нашим приложением резко возрастает, когда мы начинаем показывать HD-изображения на экране (даже одно уже может внести существенный импакт для увеличения используемой памяти).

Главное, что нужно запомнить, использование памяти ≠ размеру файла. И вот почему.

Использование памяти связано с размерами изображения, а не с размером файла (Session 416, WWDC 2018).

Всё дело в том, что для отображения изображения на экране, iOS сначала необходимо декодировать и распаковать изображение. Обычно 1 пиксель декодированного изображения занимает 4 байта памяти — 1 байт для красного, 1 байт для зеленого, 1 байт для синего и 1 байт для альфа-канала (да-да, тот самый RGB с альфой). Например:

(3648 * 5472) * 4 bytes ≈ 80MB

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

Что со всем этим делать?

Разработчики в этой статье пробовали менять масштаб и перерисовать изображение, но это не помогло. Это связано с тем, что операции для изменения размера для UIImage дороги. В процессе изменения размера iOS по-прежнему будет декодировать и распаковывать исходное изображение, вызывая нежелательный скачок памяти.

Одно из решений, которым делятся инженеры Apple — юзать даунсэмплинг.

Мы можем использовать ImageIO для изменения размера изображения перед его отображением на экране. По факту, для нас это выльется только в стоимости ресайзинга исходной картинки. Вот здесь можно чекнуть сниппет.

Флаги, которые можно использовать

1️⃣ kCGImageSourceShouldCache — когда для этого флага установлено значение false, мы сообщаем основному фреймворку, что нам нужно только создать ссылку на источник изображения и не хотим декодировать изображение сразу при создании объекта CGImageSource.

В ситуации, когда у вас нет доступа к пути к источнику изображения, вы можете создать объект CGImageSource, используя инициализатор CGImageSourceCreateWithData().

2️⃣ kCGImageSourceShouldCacheImmediately — этот флаг указывает, что декодировать изображение нужно именно в тот момент, когда мы запускаем процесс понижения дискретизации.

3️⃣ kCGImageSourceCreateThumbnailWithTransform — установка этого флага в значение true очень важно для сохранения исходной ориентации.

Подводные камни (а как же без них)

Имейте в виду, что даунсэмплинг — это процесс, который потребляет ресурсы процессора. Таким образом, по-прежнему предпочтительнее использовать правильно масштабированный источник изображения, а не понижать дискретизацию HD-изображения. Другими словами, вы должны использовать даунсэмплинг только тогда, когда вам нужно отобразить изображение, размер которого намного превышает требуемый размер на экране.

Важные моменты

Помните, что память — это конечный и общий ресурс.

Используйте встроенный в Xcode мониторинг.

Позвольте iOS выбрать ваши форматы изображений, когда это возможно.

Используйте ImageIO для понижения разрешения изображений (помните про подводные камни).

Выгружайте крупные ресурсы, которые находятся за пределами экрана.

Не игнорируйте графики памяти (memory graphs), чтобы лучше понять, что происходит.

Что почитать ещё?

📖 Deep Dive into iOS Memory.
📖 Reducing Memory Footprint When Using UIImage.
📺 Session 416, WWDC 2018.
🔗 https://developer.apple.com/documentation/imageio/cgimagesource.

@iOS Dev — отвечаем на вопросы.

BY iOS Dev




Share with your friend now:
tgoop.com/iosdev/537

View MORE
Open in Telegram


Telegram News

Date: |

bank east asia october 20 kowloon Hui said the messages, which included urging the disruption of airport operations, were attempts to incite followers to make use of poisonous, corrosive or flammable substances to vandalize police vehicles, and also called on others to make weapons to harm police. “[The defendant] could not shift his criminal liability,” Hui said. 3How to create a Telegram channel? But a Telegram statement also said: "Any requests related to political censorship or limiting human rights such as the rights to free speech or assembly are not and will not be considered."
from us


Telegram iOS Dev
FROM American