【发布时间】:2014-07-05 12:13:02
【问题描述】:
对于 JOGL 游戏,我的 fps 非常低,现在经过一些测试,我发现问题不在于 JOGL 部分,而在于纯 Java 计算。我需要定义很多float变量,占用了90%的时间。
我测试了 45 个浮点变量,其中只有 16 个获得了初始值。其余的只是float z1; float z2; 等。根据System.currentTimeMillis(),这大约需要5-10 毫秒。
但是这个带有 45 个浮点数的代码在一个由双循环调用的方法中。该方法总共被调用了 49 次 (7*7)。所有这些都在 JOGL 方法中在 JFrame 中绘制游戏,但是由于浮点变量太多,总共需要 100ms,这意味着只有 10fps。
所以基本上问题是我必须初始化 45*49=2205 个浮点数。有什么方法可以优化它以获得更好的 fps?
例如,double 会比 float 快吗?还是先在循环外定义变量,然后在循环内给它们赋值?有谁知道让这段代码运行得更快的方法?提前非常感谢。
编辑
根据要求,这里是源代码:
for (int x = -4; x < 3; x++) { // Loops 7 times
for (int y = -4; y < 3; y++) { // Loops 7 times
long t1 = System.currentTimeMillis();
float z0 = terrain.getHeight(x-1, y-1); // Simple method, but takes up about half of the time
float z1 = terrain.getHeight(x , y-1);
float z3 = terrain.getHeight(x+1, y-1);
float z4 = terrain.getHeight(x+2, y-1);
float z5 = terrain.getHeight(x-1, y );
float z6 = terrain.getHeight(x , y );
float z7;
float z8;
float z9;
float z10 = terrain.getHeight(x+1, y );
float z11 = terrain.getHeight(x+2, y );
float z12;
float z13;
float z14;
float z15;
float z16;
float z17;
float z18;
float z19;
float z20;
float z21;
float z22;
float z23;
float z24;
float z25;
float z26;
float z27;
float z28;
float z29;
float z30;
float z31;
float z32;
float z33 = terrain.getHeight(x-1, y+1);
float z34 = terrain.getHeight(x , y+1);
float z35;
float z36;
float z37;
float z38 = terrain.getHeight(x+1, y+1);
float z39 = terrain.getHeight(x+2, y+1);
float z40 = terrain.getHeight(x-1, y+2);
float z41 = terrain.getHeight(x , y+2);
float z43 = terrain.getHeight(x+1, y+2);
float z44 = terrain.getHeight(x+2, y+2);
t1 = System.currentTimeMillis() - t1;
// Some other code where I use these variables.
// Takes between 0-1 ms in total.
}
}
编辑
我现在测试了 getHeight() 方法,它占用了大约一半的时间。使用这种方法的7个变量加起来大约5ms,总共是10个。下面是getHeight()中使用的代码:
public float getHeight(float x, float y) {
long t1 = System.currentTimeMillis();
Coordinate c = new Coordinate(x, y);
for (Entry<Coordinate, Float> e : heightMap.entrySet()) { // heightMap = HashMap<Coordinate, Float>
if (e.getKey().x == c.x && e.getKey().y == c.y) {
System.out.println("getHeight: " + (System.currentTimeMillis() - t1) + " ms");
return e.getValue();
}
}
return 0f;
}
Coordinate 是我自己创建的一个类,它有一个构造函数,带有两个用于 x 和 y 的浮点参数,并将它们全局保存在类本身中。
我之所以不使用heightMap.get(c),是因为这总是抛出一个NullPointerException,而上面给出的代码永远不会到达return 0f;的最后一行。
编辑
在这个 [link] (Why are custom objects not equivalent keys for a HashMap?) 问题中找到了问题的解决方案,即我必须将 public boolean equals(Object other) 和 public int hashCode() 添加到我的自定义坐标类中。现在 getHeight 方法可以与 heightMap.get(c) 一起使用,它消除了其中的循环并使程序更快。现在总共(49 个循环)大约需要 1 毫秒。
【问题讨论】:
-
请发布您的代码。
-
在我的机器上,生成 2205 个随机浮点数需要 649 毫秒,用这些随机值初始化一个包含 2205 个浮点数的数组并将它们打印到 System.out,1000 次。所以用随机值初始化 2205 个浮点数并打印它们需要 0.65 毫秒。我看不出仅仅在你的机器上初始化 2205 个浮点数需要 100 毫秒。您可能没有正确测量,并且您可能正在尝试优化错误的部分。没有代码,反正我们也无话可说。
-
哇,你听说过数组吗?
-
“初始化”那些未初始化的变量几乎没有任何成本。成本(一点)仅仅是拥有这么多,因为您的堆栈帧变得太大而无法轻松容纳单个缓存行。
-
您在
getHeight中有一个println。把它拿出来,你就会放大。
标签: java performance