有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

数组Java节省2d分幅:for循环在每次迭代中变慢,每次迭代长达5秒,每次迭代10000次

我目前正在开发一款基于瓷砖的2d游戏。目前,我正在写一个拯救全世界的过程。一般来说,一个世界是10000 x 10=1.100.000个街区大。显然,这对java来说不应该是个问题,但确实是

以下是我的循环:

Material[][] blocks = g.gameState.getLevel().tiles;
int y = 0;
int blocksHor = g.gameState.getLevel().getBlocksHor();

for(int x = 0; x < blocksHor; x++) {

    world += blocks[y][x] + " ";

    if(x >= blocksHor - 1) {
        x = 0;
        y++;
        System.out.println("LAYER " + y + " => " + (System.currentTimeMillis() - now) + " ms");
        now = System.currentTimeMillis();
    }
}

这个循环有点难以理解,但我已经尽可能地优化了。以下是控制台输出:

LAYER 1 => 86 ms
LAYER 2 => 276 ms
LAYER 3 => 424 ms
LAYER 4 => 618 ms
LAYER 5 => 561 ms
LAYER 6 => 541 ms
LAYER 7 => 755 ms
LAYER 8 => 885 ms
LAYER 9 => 1036 ms

最后,这些过程将持续50秒或更长时间

这个循环怎么了?我真的不知道该怎么解决这个问题

谢谢:) -菲尔


共 (1) 个答案

  1. # 1 楼答案

    如果你给出的代码确实代表了你的问题,那么这个问题很有可能发生在

    world += blocks[y][x] + " ";
    

    这有几个性能问题。首先,world必须有类型String,并且String是不可变的。因此,无论何时通过+操作符连接它们,都必须创建一个新的操作符来保存结果。在该语句的每次执行中,您至少会执行两次,总共会产生超过200万个最终必须收集的垃圾对象

    此外,world的中间值在大小上稳步增加,因此所有这些临时值消耗的组合内存与块总数的平方成正比。即使每个块的字符串值只有一个字符长,这也会占用大量内存。你最终会遇到严重的垃圾收集问题,而且随着你的继续,问题确实会越来越严重

    作为改进此的第一个尝试,您可以考虑将数据累积到^ {< CD6>}而不是^ {< CD2>}:

    StringBuilder worldBuilder = new StringBuilder();
    
    // ...
    
    worldBuilder.append(blocks[y][x]).append(' ');
    

    通过创建更少的垃圾,这将显著缓解GC问题,但最终仍然需要一个相当大的对象来保存整个状态。因此,我还建议将数据累积成更小的数据块,边输出边处理,而不是在输出任何数据之前在内存中构建整个表示

    您可能还想看看Material.toString()的实现,因为如果它也通过执行字符串连接产生大量垃圾,那么这将放大问题