Предупреждения памяти iPhone OS. Что означают разные уровни?

Что касается черного искусства управления памятью на устройствах iPhone OS: что означают разные уровни памяти. 1-й уровень? Уровень 2? Циферблат переходит на 11?

Контекст: после обширного периода стресс-тестирования памяти - включая запуск моего приложения iPad с приложением для воспроизведения музыкального плеера iPod, я склонен игнорировать случайные, но редкие предупреждения о памяти, которые я получаю. Мое приложение никогда не срабатывает. Когда-либо. Мое приложение не содержит утечек. И, что ж, предупреждения о мэмах просто не кажутся важными.

Спасибо,
Дуг

Ответ 1

В основном предупреждения означают, что устройство работает на низком уровне в памяти, и что: "Если бы вы могли освободить некоторую память, которую вы активно не используете, это будет swell!". Если ваше управление памятью плотно, и у вас нет объектов, которые можно практически отбросить, просто передайте сообщение и проигнорируйте его.

Ответ 2

Предупреждения уровня памяти регистрируются SpringBoard. В качестве разработчика приложений вам не нужно заботиться об этом. Просто отвечать на -{application}didReceiveMemoryWarning достаточно.


Существует 4 уровня предупреждений (от 0 до 3). Они задаются из наблюдателя памяти ядра и могут быть получены с помощью не столь публичной функции OSMemoryNotificationCurrentLevel().

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

Как запускаются уровни, не документируется. SpringBoard настроен на выполнение следующих операций на каждом уровне памяти:

  • Предупреждение (не нормальное). Перезапустите или запустите автоматическое повторное использование несущественных фоновых приложений, например. Почта.
  • Срочно - закройте все фоновые приложения, например. Safari и iPod.
  • Критически и дальше - Ядро вступит в силу, возможно, убив SpringBoard или даже перезагрузив.

Убивание активного приложения (jetsam) не выполняется SpringBoard, но launchd.

Ответ 3

От OSMemoryNotification.h,

/*
** Threshold values for notifications
*/

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

totoal 5 уровней предупреждения памяти (-1,3).

Что касается предупреждения об уровне памяти, ответ @KennyTM превосходный.

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


Что делать, если у вас есть предупреждение о уровне памяти?

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


Как наблюдать предупреждение о уровне памяти?

От http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html

Когда система отправляет предупреждение с низкой памятью в ваше приложение, немедленно ответьте. iOS уведомляет все запущенные приложения всякий раз, когда количество свободной памяти падает ниже безопасного порога. (Он не уведомляет приостановленные приложения.) Если ваше приложение получает это предупреждение, оно должно освобождать как можно больше памяти. Лучший способ сделать это - удалить сильные ссылки на кеши, объекты изображений и другие объекты данных, которые можно воссоздать позже.

UIKit предоставляет несколько способов получения предупреждений с низкой памятью, в том числе следующее:

  • Внедрение applicationDidReceiveMemoryWarning: метод вашего приложения делегат.
  • Переопределите метод didReceiveMemoryWarning в вашем обычном Подкласс UIViewController.
  • Зарегистрируйтесь, чтобы получить UIApplicationDidReceiveMemoryWarningNotificationnotification.

Как уменьшить объем памяти приложений?

  • Устранить утечки памяти.
  • Сделать файлы ресурсов как можно меньше.
  • Используйте основные данные или SQLite для больших наборов данных.
  • Загружать ресурсы лениво.
  • Создайте свою программу, используя опцию Thumb.

Подробности http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html


Как распределить память с умом?

  • Уменьшите использование автореализованных объектов: с автоматической ссылкой подсчета (ARC), лучше выделять/инициализировать объекты и компилятор выпустит их для вас в соответствующее время. Это правда даже для временных объектов, которые в прошлом могли иметь автореализован, чтобы не допустить их текущий метод.
  • Ввести ограничения размера ресурсов: избегать загрузки большого файла ресурсов когда будет делать меньший. Вместо использования изображения с высоким разрешением, используйте тот, который соответствует размерам для устройств на базе iOS. если ты должны использовать большие файлы ресурсов, находить способы загрузки только части файл, который вам нужен в любой момент времени. Например, вместо загрузите весь файл в память, используйте функции mmap и munmap для отображения частей файла в и из памяти. Для большего информация о отображении файлов в память.
  • Избегайте неограниченных наборов проблем: для неограниченных наборов проблем может потребоваться произвольно большой объем данных для вычисления. Если набор требует больше, чем доступно, ваше приложение может не расчеты. Ваши приложения должны избегать таких наборов, когда это возможно, и работайте над проблемами с известными ограничениями памяти.