2012-03-29 2 views
0

Я пишу несколько сложный игровой движок в Android.Android: Обновление потока заставляет GC запускать тонну

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

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

Состояние игры имеет сцену, которая обновляется. Сцены состоят из корневого узла, который создает простую структуру графа сцены.

Корни являются узлами, у которых есть дети, которые также обновляются и так далее, и так далее.

В любом случае, это все хорошо и хорошо, и отлично работает, пока я не получу миллион из них в моем Logcat: 03-29 09: 23: 22.866: D/dalvikvm (18554): GC_CONCURRENT освобожден 511K, 52% бесплатно 2773K/5767K, внешний 77K/587K, приостановленный 2ms + 3ms

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

(GameLgoic) 
public void onUpdate(float deltaTime) 
    { 
     if (gameState != null) 
      gameState.onUpdate(deltaTime); 
    } 
(GameState) 
public void onUpdate(float deltaTime) 
    { 
     scene.onUpdate(deltaTime); 
    } 
(Scene) 
public void onUpdate(float deltaTime) 
    { 
     root.onUpdate(deltaTime); 
    } 
(SceneNode) 
public void onUpdate(float deltaTime) 
    { 
     for (int i = 0; i < children.size(); ++i) 
     { 
      children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here 
     } 
    } 

Если я закомментировать children.get (I) .onUpdate (DeltaTime) Там нет утечек! Мой ум настолько ошеломлен. Спасибо, парни.

+1

Хорошая новость: Ваша утечка не вызов OnUpdate(). Это код внутри этого метода. Добавьте соответствующие фрагменты кода. – WarrenFaith

+1

Просьба показать определение 'children' и связанного с ним метода' onUpdate'. – Gray

+2

О, и каждый раз, когда вы вызываете 'size()' в цикле, умирает котенок. Вы должны проверить руководство по эффективности в официальной документации :) – WarrenFaith

ответ

2

У меня возникла аналогичная проблема, когда я сделал игру для Android. Единственный способ избавиться от этого - это код embedded-C-Style. Так что если вы хотите цикл, повторно использовать переменную подсчета, а также переменную ограничительную, всякий раз, когда это возможно, например, так:

int i; 
int max 
void loop(){ 
    max = bla.size(); 
    for(i=0; i<max; i++){ ... } 
} 

То же самое касается буквально все, что вы касаетесь. Поэтому вы можете учесть ссылки на объекты, которые вам больше не нужны, и переработать их позже.

Это безумие, какая разница в моей игре, реализующей эти изменения. Рамка удвоилась, значительно уменьшилось отставание и так далее.

Вы должны изучить инструмент DDMS, который является delieverd, который затмение Android SDK. Вы можете использовать его для отслеживания распределения, чтобы избежать этих проблем.

Addtionally, вы должны рассмотреть возможность удаления всех интерпретаторов, поскольку они выделяются каждый раз, когда вы переходите в цикл и не можете быть переработаны. Так что лучше петля вручную и несколько раз переходить по вашим спискам (get(x) в цикле), чем ждать в сборщике мусора в долгосрочной перспективе.

+0

, но, как он упомянул: «Если я прокомментирую child.get (i) .onUpdate (deltaTime) Нет утечек! Причина в коде этого метода, а не сам цикл ... – WarrenFaith

+0

в этом случае синтаксис 'for (Child c: children)' также может быть удобным. – Jave

+0

Я просто расширил свой ответ, чтобы покрыть это: итераторы также будут объектом сбора GC, так что, к сожалению, это не вариант. – devsnd

0

Сначала уточнить терминологию - вы не есть a memory leak. Утечка памяти возникает, когда использование памяти вашего приложения растет и растет, потому что оно не освобождает память, которую она больше не использует. У вас есть проблема - вы выпускаете много неиспользуемой памяти, которая должна быть garbage collected.

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

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

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

Наконец, мелочь, вы можете заменить:

for (int i = 0; i < children.size(); ++i) 
{ 
    children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here 
} 

с a for loop:

for (SomeClass child : children) { 
    child.onUpdate(deltaTime); 
} 
+0

Плохо дать ему выстрел! Спасибо друг. – DubyaDubyaDubyaDot

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