计算对象而不会产生太多垃圾

时间:2014-07-03 22:09:47

标签: java performance garbage-collection

目前我正在为Android开发游戏。为此,我的所有对象都有一个Vec3位置。这是该课程的摘录:

public class Vec3 {
    public float x, y, z;

    public Vec3(float x, float y, float z) {
        this.x = x; this.y = y; this.z = z;
    }

    public Vec3 add(Vec3 v) {
        return new Vec3(this.x + v.x, this.y - v.y, this.z + v.z);
    }

    public Vec3 sub(Vec3 v) {
        return new Vec3(this.x - v.x, this.y - v.y, this.z - v.z);
    }
}

现在假设我要运行此代码,其中abc是来自Vec3类的向量:

a.add(b).sub(c);

如果我使用许多不同的向量运行此代码,它会在我的游戏中滞后,因为有时当不再需要向量时,垃圾收集器会同时将它们全部删除。我认为我可以用variable pool来解决这个问题,但问题就是这个问题。我不知道我的游戏中何时不再使用该向量所以我不知道在哪里检查向量

另一个问题是我在add和sub方法中生成了很多矢量对象。我想计算向量而不改变它们本身,这就是为什么我每次都返回一个新的Vec3。假设我运行此代码:

a.add(b).add(b).add(b).add(b).add(b).sub(c);

我生成了六个新的矢量对象,但如果你考虑到这一点,我只需要一个来计算矢量并存储结果而不改变原始矢量。这也是我用variable pool无法解决的问题。

您是否有任何想法如何以有效的方式解决这些问题?

2 个答案:

答案 0 :(得分:1)

您可以编写就地addsub方法:

public Vec3 addInPlace(Vec3 v) {
    x += v.x;
    y += v.y;
    z += v.z;
    return this;
}

// and similarly for subInPlace

然后使用它们以避免产生额外的临时工具:

temp = a.add(b);
temp.addInPlace(b).addInPlace(b).addInPlace(b).addInPlace(b).subInPlace(c);

您必须明确地管理对象重用,否则会失去Vec3个对象的不变性。这两件事都很糟糕。

答案 1 :(得分:0)

在你更复杂的例子中

a.add(b).add(b).add(b).add(b).add(b).sub(c);

你可以通过使用更强大的操作消除大部分垃圾

a.mulAdd(4, b, -1, c);

我会害怕乘法时间,但不会太多。你也可以编写像

这样的专门操作
a.addFourSubOne(b, c);

这听起来很愚蠢,因为你永远无法实现可能使用的所有操作。 OTOH您可以轻松实现ypu <​​em>真正使用的所有操作。


我可能建议使用可变对象。您可以为它们提供变异和复制操作,称为add / addInPlaceplus / add。你也可以实现可变版本和不可变版本(这很快就会很无聊,但是你可以通过不实现你实际上不需要的任何东西来管理它。)