Java性能优化
对于JOGL游戏,我的fps非常低,现在通过一些测试,我发现问题不在JOGL部分,而是在纯Java计算中。我需要定义很多浮点变量,这占用了90%的时间
我测试了45个浮点变量,其中只有16个得到初始值。其余的只是float z1; float z2;
,等等。根据System.currentTimeMillis()
,这大约需要5-10毫秒
但这段带有45个浮点数的代码位于一个由双循环调用的方法中。这个方法总共调用了49次(7*7)。所有这些都在JOGL方法中,以JFrame绘制游戏,但由于有这么多浮点变量,总共需要100毫秒,这意味着只有10帧
所以基本上问题是我必须初始化45*49=2205个浮点数。有没有办法优化它以获得更好的fps
例如,双精度浮点数会比浮点数快吗?或者先在循环外定义变量,然后在循环内给它们赋值,这会有帮助吗?有人知道如何让代码运行得更快吗?先谢谢你
编辑
根据要求,以下是源代码:
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()方法,它占用了大约一半的时间。使用此方法的七个变量加起来约为5 ms,其中总数为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;
}
坐标是我自己创建的一个类,它有一个构造函数,其中包含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毫秒
# 1 楼答案
爪哇的高性能计算,您可能会考虑USI JNI(java本机接口)——虽然它需要C++知识。要快速开始,请查看here
# 2 楼答案
请注意,某些操作系统必须使用全屏独占模式才能为您提供足够的资源
在循环之外定义变量不会有帮助,因为Java优化了代码,而在循环内部定义变量实际上为Java提供了提高性能的提示。我认为(我只能猜测,因为你没有发布代码)是,你可以考虑使用一个长数组。在循环中使用它们非常有效,而且它们也在内存中一个接一个地分配,所以缓存可以有效地使用
对我来说,填充2025 long需要略高于一毫秒的时间,包括对random的调用。nextLong()方法
使用并行流,此任务花费的时间更少。通常在1毫秒以下