Утечки. XCode Leaks & Allocations. Осторожно XML

Я люблю сложные задачи, но терпеть не могу, когда не ясно откуда идет проблема, как с ней бороться и куда вообще копать. Третий день бьюсь над проблемами с памятью: после загрузки и выгрузки игровой сцены есть большая утечка порядка 20Мб, что, мягко говоря, много. Изначально я пробовал пользоваться инструментом Leaks, но он не показывал практически ничего. Тогда  я обратил свое внимание на инструмент Allocations. Разобраться в том как с ним работать в моем случае было довольно большой головной болью.

Итак принцип по которому я работал был следующим:

  1. Загружаю главный экран. Делаю снимок.
  2. Загружаю игровой экран, загружаю главный экран, делаю снимок.
  3. Повторяю пункт 2 еще несколько раз.
  4. Открываю один из средних снимков и смотрю из-за каких объектов выросла куча
  5. Устраняю те проблемы, причина которых стала очевидной
  6. Повторяю все с пункта 1 до тех пор, пока результат работы приложения меня не устроит

А теперь в кратце о неожиданных результатах, с которыми я столкнулся.

XML очень дорогой формат

Итак, я начну с минусов:

  • Слишком большие файлы - много избыточной информации
  • Довольно долгий парсинг
  • Требует довольно большого объема памяти

Плюсы:

  • Удобочитаемость - важно особенно на этапе активной разработки, когда нужно что то поменять на лету
  • Можно сжать в архив

Большие файлы для меня проблема, так как максимальный размер бандла ограничен, а xml файлов у меня много. Скорость парсинга, конечно, зависит от библиотеки для работы с xml, но, конечно, она несравнима, например, с обработкой бинарного формата. А вот проблема с памятью для меня оказалась большой неожиданностью. Я работаю c xml при помощи tinyxml. Ранее ресурсы были организованы таким образом, что хранился распарсенный xml, и, каждый раз применяя ресурс, я проходил по дереву для получения нужных мне параметров. Здесь открылись две проблемы: один XMLElement в памяти занимал 4Кб, а теперь, если представить сколько этих элементов в среднего размера xml’ке, то можно понять, что это катастрофично. Первым делом я перделал логику таким образом, чтобы парсить xml только при загрузке ресурса, а затем создавать объекты из заранее заполненных структур данных. Это не только освободило изрядный кусок памяти, но и дало большой прирост в производительности. Как показала практика, поиск по элементам в xml намного медленнее, чем, скажем, поиск по unordered_map’у. В итоге, избавившись от постоянной работы с xml, я только выиграл. Следующим шагом, я думаю, стоит перейти с xml на бинарный формат.