安卓:更新线程导致GC运行大量



我正在Android中编写一个有点复杂的游戏引擎。

目前我有一个线程用于更新子系统。

更新方法是基于当前游戏状态更新游戏逻辑的方法。

游戏状态有一个更新的场景。场景由一个根节点组成,从而形成一个简单的场景图结构。

根是具有也被更新的子节点的节点,依此类推。

无论如何,这一切都很好,很好,效果很好,直到我在我的Logcat:03-29: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
        }
    }

如果我评论掉孩子们。get(I).onUpdate(deltaTime)没有泄漏!我的头脑是如此的困惑。谢谢大家。

我在为Android制作游戏时遇到了类似的问题。摆脱这种困境的唯一方法是编写嵌入C风格的代码。因此,如果你想要一个循环,尽可能重复使用你的计数变量和边界变量,就像这样:

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

同样的道理也适用于你接触到的其他东西。因此,您可能会考虑保留对不再需要的对象的引用,并在以后回收它们。

实现这些改变对我的游戏产生了多么大的影响,真是太疯狂了。帧速率翻了一番,大大减少了延迟等等

你应该研究一下DDMS工具,它是eclipse Android SDK开发的。您可以使用它来跟踪分配,以避免这些问题。

另外,您应该考虑删除所有interator,因为它们是在每次跳到循环中时分配的,不能回收。因此,手动循环并多次遍历列表(循环中的get(x))比长期等待垃圾收集器要好。

首先要澄清术语-您不存在内存泄漏。当你的应用程序的内存使用量不断增长时,就会发生内存泄漏,因为它没有释放不再使用的内存。您有相反的问题——您释放了大量未使用的内存,这些内存必须进行垃圾回收。

释放未使用的内存通常是件好事;只有当清理释放的内存所需的垃圾回收导致性能问题时,它才会成为问题,这就是您在这里看到的。

到目前为止,您发布的代码没有什么大问题。问题似乎存在于onUpdate()方法内部,因此您可以发布该方法的代码。

通常,您可以通过尽可能重用对象而不是销毁和创建对象来减少垃圾收集。

最后,一个小问题,你可以替换:

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

带有for循环:

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

最新更新