Как я могу отслеживать пики памяти? (Это пики с p, а не l.)

У меня есть приложение для киоска, которое, по сути, показывает кучу слайдов с различными битами информации о них. Сначала я начал кодировать это год назад, когда я начинал с разработки Objective-C и iOS. Я считаю, что мой стиль кода намного чище, чем тот, который был, и я гораздо более опытен, поэтому решил переписать с нуля.

Я запустил приложение с помощью инструмента Allocations, чтобы узнать, что такое использование памяти. Учитывая, что это приложение для киоска, все должно работать плавно, без утечек. (Конечно, все приложения должны запускаться без утечек, но приложение для киоска делает это еще более важной задачей.) Я видел некоторые интересные результаты, поэтому я также запускал старую версию кода.

Запустив более старую версию кода, я вижу, что даже почти 1,25 мегабайта памяти используется. Кажется, что все выделено и освобождено по мере необходимости. Однако в моей новой реализации я вижу что-то совсем другое. Использование памяти продолжает прыгать в маленьких "плато", а затем, по-видимому, достигает максимума примерно в 1,47 мегабайта использования. Вот как выглядит новый отчет Allocations после работы более 10 часов:

enter image description here

Меня беспокоят по нескольким причинам.

  • Нечетный шаблон в начале прогона.
  • Выделения, по-видимому, достигают максимума в 1,47 мегабайта, но его запуск за одну ночь показывает, что он будет постепенно использовать все больше и больше памяти с течением времени. Это не может быть хорошо.

Есть несколько заметных различий между старым проектом и новым.

  • Более старый использует Plists в качестве хранилища резервных копий (я вручную читаю и пишу в файл plist.) В новом проекте используются основные данные.

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

  • Оба класса используют класс factory для создания слайдов. В старом проекте класс factory был одиночным. Я думал, что превращение его в нормальный класс поможет с проблемами памяти, поскольку синглтон никогда не был выпущен. (Следовательно, его свойства не были выпущены. В новом проекте класс factory выпускается, поэтому я не уверен, почему он все еще занимает всю эту память (если это вызвало проблему.

  • В старом проекте используются строковые константы в разных местах. Новый код использует массивное перечисление для одного и того же. (Новый код в целом использует больше констант.)

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

Буду признателен, если кто-нибудь поможет мне указать в правильном направлении.

Edit:

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

Ответ 1

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

Это классический случай "заброшенных объектов" или "аккреции использования". То есть у вас есть приложение, которое при его запуске создает граф объектов в памяти как обычную часть использования. Объекты не просачиваются, потому что они все еще подключены к графику живых объектов. Скорее всего, объекты являются частью какого-либо кеша (чаще всего для записи) или механизма, включающего историческое состояние (стек отмены является потенциальным источником для аккреции).

Чтобы исправить это, вы должны убедиться, что граф объекта соответствующим образом обрезается по мере запуска вашего приложения. Кэши должны, как правило, использовать алгоритм обрезки с наименьшим числом последних [LRU], который ограничивает размер кеша. Если ключ кеша когда-либо недействителен, эти данные также должны быть обрезаны.

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

Используйте анализ Heapshot - он был создан, чтобы помочь справиться с этими проблемами.

Я написал подробное руководство "Как"; Когда утечка не утечка?