Java性能优化

Java性能优化,java,performance,Java,Performance,对于JOGL游戏,我的fps非常低,现在通过一些测试,我发现问题不在JOGL部分,而是在纯Java计算中。我需要定义很多浮点变量,这占用了90%的时间 我测试了45个浮点变量,其中只有16个得到初始值。剩下的只是浮点数z1;浮点数z2;,根据System.currentTimeMillis,这大约需要5-10毫秒 但这段带有45个浮点数的代码位于一个由双循环调用的方法中。这个方法总共被调用49次7*7。所有这些都在JOGL方法中,以JFrame绘制游戏,但由于有这么多浮点变量,总共需要100毫秒

对于JOGL游戏,我的fps非常低,现在通过一些测试,我发现问题不在JOGL部分,而是在纯Java计算中。我需要定义很多浮点变量,这占用了90%的时间

我测试了45个浮点变量,其中只有16个得到初始值。剩下的只是浮点数z1;浮点数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.getc,是因为它总是抛出NullPointerException,而上面给出的代码永远不会到达返回0f;的最后一行

编辑


在[link]问题中找到了问题的解决方案,即我必须将公共布尔equalsObject other和公共int hashCode添加到我的自定义坐标类中。现在getHeight方法可以与heightMap.getc一起使用,这将删除其中的循环,并使程序更快。总共有49个循环,现在大约需要1毫秒。

请注意,某些操作系统必须使用全屏独占模式才能为您提供足够的资源

在循环之外定义变量不会有帮助,因为Java优化了代码,而在循环内部定义变量实际上为Java提供了提高性能的提示。我想,我只能猜测,因为你没有张贴代码,你可以考虑使用一个数组的长。在循环中使用它们非常有效,而且它们也在内存中一个接一个地分配,所以缓存可以有效地使用

对我来说,填充2025 long需要略高于1毫秒的时间,包括对random.nextLong方法的调用

public Long fillLongs(int numberofLongs) {

    long[] longs = new long[numberofLongs];
    Random r = new Random();

    long start = System.currentTimeMillis();

    for (long l : longs) {
        l = r.nextLong();
    }

    long end = System.currentTimeMillis();

    return end - start;

}
使用并行流,此任务花费的时间更少。通常在1毫秒以下

public Long fillLongs(int numberofLongs) {

    Long[] longs = new Long[numberofLongs];
    List<Long> longList = Arrays.asList(longs);
    Random r = new Random();

    long start = System.currentTimeMillis();

    longList.parallelStream().forEach(l -> {
        l = r.nextLong();
    });

    long end = System.currentTimeMillis();

    return end - start;

}

对于爪哇的高性能计算,您可能会考虑USI JNI java本地接口——尽管它需要C++知识。要快速开始,请看一看。

请发布您的代码。在我的机器上,生成2205个随机浮点值需要649毫秒,使用这些随机值初始化2205个浮点值的数组,并将它们打印到System.out,1000次。因此,使用随机值初始化2205浮点并打印它们需要0.65毫秒。我不明白在你的机器上初始化2205个浮点数怎么可能需要100毫秒。您可能测量不正确,并且您可能试图优化错误的零件。如果没有代码,我们什么也说不出来了。哇,你听说过数组吗?初始化那些未初始化的变量几乎不需要任何成本。花费很少的只是拥有这么多,因为堆栈帧变得太大,无法轻松容纳单个缓存线。首先,Java已经在HPC中使用多年,例如IBM。其次,他的计算非常简单,C只能在一些非常特殊的情况下给出加速。第三,他从未说过他是针对Android的,JNI在桌面环境中受J2SE支持。最后,他的问题来自对哈希映射的天真使用。