Android: обновление потока приводит к тому, что GC запускает тонну - PullRequest
0 голосов
/ 29 марта 2012

Я пишу несколько сложный игровой движок в Android.

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

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

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

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

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

Я выделил причину утечки в цикле обновления, так как, когда я закомментирую свой метод обновления подсистем, сообщений 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) Утечек нет!Мой разум так поражен.Спасибо, ребята.

Ответы [ 2 ]

2 голосов
/ 29 марта 2012

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

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

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

Безумие, какое это имеет значение для моей игры, в которой реализованы эти изменения.Частота кадров увеличилась вдвое, значительно сократились лаги и т. Д.

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

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

0 голосов
/ 29 марта 2012

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

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

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

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

Наконец, второстепенный пункт вы можете заменить:

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

с a для цикла :

for (SomeClass child : children) {
    child.onUpdate(deltaTime);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...