我正在开发一款使用Vector2类来执行所需计算的游戏。 这是一个你可以想象的简单类:字段“x”,“y”,一些方法,如add(),sub(),scl()
如果我正在创建这样的方法:
public void doSomething() {
Vector2 offset = new Vector2(10, 3);
offset.rotate(45).add(3, 2);
Vector2 position = new Vector2(20, 35);
position.sub(4, 5).add(offset);
// something else
}
创建了很多Vector2类实例,GC有很多工作要做,在一个游戏步骤(1/40秒)中创建了200多个向量。因此,当GC运行时,游戏FPS正在下降。
我尝试使用池来回收创建的实例,但这是非常糟糕的错误,收集和处理它们比GC花了更多的时间。
所以我想预先创建实例并使用它们:
private final Vector2 v1 = new Vector2(), v2 = new Vector2();
public void doSomething() {
Vector2 offset = v1;
offset.set(10, 3);
offset.rotate(45).add(3, 2);
Vector2 position = v2;
position.set(20, 35);
position.sub(4, 5).add(offset);
// something else
}
v1和v2是类字段,它们在创建对象时实例化一次。 通过这种方式,我实现了性能并为变量保留了友好名称。
然而,我想知道它是否是一个好的解决方案,并被告知使用它的潜在风险。或者还有另一种方法可以解决这个问题吗?
答案 0 :(得分:3)
当你经常尝试自己时,从根本上远离物体会怎么样?
将(x, y)
打包为一个int中的两个short,或者将两个int打包为long。使用静态函数创建一个抽象类来进行操作。
public class Vector2 {
private Vector2 {}
public static short x(int v) {
return (short)(v & 0xFFFF);
}
public static int add(int u, int v) {
...
}
答案 1 :(得分:2)
潜在风险是并发修改,原因可能是:
1)您的doSomething
方法被多个线程同时调用(在之前的情况下,每个调用创建了自己的本地Vector2
实例)。解决方案:添加所需的同步。即使在单线程场景中,如果同时调用该方法,也可能会出现问题。
2)即使在单线程情况下,你(或其他程序员)也忘记了向量是在本地"本地"使用并从另一种方法修改它。解决方案:记录好。