2012-06-04 2 views
1

Я разрабатываю игру, используя Cocos2D для iOS.Как узнать, что ест память в Cocos2d

Есть несколько сцен, таких как меню и т. П., И основная игровая сцена. На главной сцене есть только три динамических объекта. Эти объекты периодически стреляют друг в друга (пока эти объекты не будут убиты или не выведены из сцены).

Теперь проблема: игра постоянно поглощает память. И я хочу узнать, что я делаю неправильно.

Нет явных утечек, таких как чрезмерно удерживаемые объекты. Сцена получает dealloc ed, объекты удаляются с родителей и очищаются, анимации останавливаются и т. Д.

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

+ (void) reportMemory 
{ 
    struct task_basic_info info; 
    mach_msg_type_number_t size = sizeof(info); 
    kern_return_t kerr = task_info(mach_task_self(), 
            TASK_BASIC_INFO, 
            (task_info_t)&info, 
            &size); 
    if (kerr == KERN_SUCCESS) 
     NSLog(@"Memory in use (in Kbytes): %f", info.resident_size/1024.0); 
    else 
     NSLog(@"Error with task_info(): %s", mach_error_string(kerr)); 
} 

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

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

Что вы предложите мне посмотреть? В основном, я ищу советы о том, как отлаживать операции с памятью в моем случае.

EDIT (Что помогло мне):

Оказалось, что у меня был NSZombieEnabled включен. В основном, это был основной фактор для увеличения потребления постоянной памяти. Некоторую полезную информацию и наконечник можно найти в @coneybeare answer

Вторая полезная вещь - использовать инструменты (утечки и распределения), как предлагалось @Jack. Это помогло мне найти пару тонких утечек.

+0

Каков размер ваших общих байтов жизни? – CarlJ

+0

@meccan сначала около 42 Мб (количество атласов спринта предварительно кэшировано в этот момент), а затем он растет примерно на 2-5 МБ за каждый прогон сцены до 125 Мб. После этого процесс будет уничтожен ОС. – Bobrovsky

+0

О, сумасшедший, слишком много. Вы использовали какие-либо кешированные изображения? – CarlJ

ответ

5

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

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

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

  • в ответственных цепях вызова, где обнаружена утечка
  • , нажав на маленькую стрелку в B вы можете увидеть точное живой прогрессию памяти просочилась (например, когда он был malloc'd, сохранил, выпущенный и все)

Leaks Xcode

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

enter image description here

С этим я всегда был в состоянии найти любые связанные с памятью проблемы!

+0

+1 Не пишите свои собственные инструменты для отладки, когда вы можете потратить столько же времени на изучение более мощных! – benzado

+0

@Jack спасибо. Я попробую снова использовать Allocations. – Bobrovsky

3

Я хотел бы начать, глядя на кэш текстуры следующим образом:

[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo]; 

сделать это в начале каждой сцены. Текстуры могут быть реальными бородами памяти. Возможно, вы каким-то образом держитесь за некоторые текстуры (быстрый способ сделать это через spriteFrames, которые также находятся в кеше где-то), или сохраненные ссылки могут быть в вашей модели данных где-то. Вот мой #if DEBUG memoryWarning делегат:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : before purging all caches"); 
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo]; 
    [[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames]; 
    [[CCDirector sharedDirector] purgeCachedData]; 
    CCLOG(@"AppDelegate<applicationDidReceiveMemoryWarning> : after purging all caches"); 
    [[CCTextureCache sharedTextureCache] dumpCachedTextureInfo]; 
} 
+0

Я пробовал почти то же самое. Результат вроде как ожидаемый (я не видел никаких проблем). – Bobrovsky

+1

+1. Не полагайтесь на applicationDidReceiveMemoryWarning, чтобы сохранить вас, хотя иногда приложение не успевает его называть. Лучше убирать, как вы идете. В некоторых интенсивных сценах на старых устройствах я запускаю эти чистки на таймере каждые пару секунд. –

+0

@ DanyalAytekin: полностью, это была фаза «проблемы открытия» проекта. Подобные фрагменты кода теперь также появляются здесь и там повсюду в приложении, особенно вблизи переходов, с особым вниманием к тому, чтобы дать циклу запуска возможность очистить объекты автозапуска. – YvesLeBorg

2

Убедитесь, что вы не сохраняя какие-либо предметы в пределах иерархии Кокосовой; Cocos, встроенный в методы очистки объектов, не всегда работает, если Cocos не имеет единоличного контроля и владения ими; если вы храните Sprites или Layers в качестве сохраненных iVars, увеличивая их количество ссылок за пределы обычного права на Cocos, тогда они могут не очищаться, как ожидалось. По этой причине я всегда использую свойства assign при сохранении указателей на объекты Cocos.

+0

Спасибо. Есть ли что-нибудь, что я могу прочитать об этой проблеме (книги или статьи)? Я сохраняю анимацию в нескольких местах и ​​теперь задаюсь вопросом, как я должен делать то же самое, не сохраняя. – Bobrovsky

+1

Книга Штеффена Итергейма (правописание?) И сам Штеффен здесь, на SO, могут многое сказать о проблемах памяти с Cocos2D – johnbakers

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