Java节省2d分幅:对于循环,每次迭代速度会变慢,10000次迭代最多5秒
我目前正在开发一个基于瓷砖的2d游戏。目前,我正在写一个拯救全世界的过程。一般来说,一个世界是10000 x 10=1.100.000块大。显然,这对java来说不应该是个问题,但确实是 这是我的循环:Java节省2d分幅:对于循环,每次迭代速度会变慢,10000次迭代最多5秒,java,arrays,for-loop,iteration,2d-games,Java,Arrays,For Loop,Iteration,2d Games,我目前正在开发一个基于瓷砖的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 < blocksH
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();
}
}
这些过程将在结束时持续50秒或更长时间
这个循环有什么问题?我真的不知道该怎么解决这个问题
谢谢:)
-phil如果您提供的代码确实代表了您的问题,那么问题很有可能出现在
world += blocks[y][x] + " ";
这有几个性能问题。首先,world
必须具有类型String
,并且String
是不可变的。因此,无论何时通过+
操作符连接它们,都必须创建一个新的操作符来保存结果。在该语句的每次执行中,您至少会执行两次,总共会产生超过200万个最终必须收集的垃圾对象
此外,world
的中间值在大小上稳步增加,因此所有这些临时值消耗的组合内存与块总数的平方成正比。即使每个块的字符串值只有一个字符长,这也会占用大量内存。您最终会遇到严重的垃圾收集问题,而且随着您的继续,这些问题确实会越来越严重
作为改进的第一个尝试,您可以考虑将数据累积到<代码> StringBuilder <代码>中,而不是<代码>字符串> >:
StringBuilder worldBuilder = new StringBuilder();
// ...
worldBuilder.append(blocks[y][x]).append(' ');
这将通过创建更少的垃圾来显著缓解GC问题,但最终仍然需要一个相当大的对象来保存整个状态。因此,我还建议将数据累积成更小的数据块,边输出边处理,而不是在输出任何内容之前在内存中构建整个表示
您可能还想看看
Material.toString()
的实现,因为如果它也通过执行字符串连接产生大量垃圾,那么这将放大问题。如果您提供的代码确实代表了您的问题,那么问题很有可能在
world += blocks[y][x] + " ";
这有几个性能问题。首先,world
必须具有类型String
,并且String
是不可变的。因此,无论何时通过+
操作符连接它们,都必须创建一个新的操作符来保存结果。在该语句的每次执行中,您至少会执行两次,总共会产生超过200万个最终必须收集的垃圾对象
此外,world
的中间值在大小上稳步增加,因此所有这些临时值消耗的组合内存与块总数的平方成正比。即使每个块的字符串值只有一个字符长,这也会占用大量内存。您最终会遇到严重的垃圾收集问题,而且随着您的继续,这些问题确实会越来越严重
作为改进的第一个尝试,您可以考虑将数据累积到<代码> StringBuilder <代码>中,而不是<代码>字符串> >:
StringBuilder worldBuilder = new StringBuilder();
// ...
worldBuilder.append(blocks[y][x]).append(' ');
这将通过创建更少的垃圾来显著缓解GC问题,但最终仍然需要一个相当大的对象来保存整个状态。因此,我还建议将数据累积成更小的数据块,边输出边处理,而不是在输出任何内容之前在内存中构建整个表示
您可能还想看看
Material.toString()
的实现,因为如果它也通过执行字符串连接产生大量垃圾,那么这将放大问题。可能尝试?可能尝试?哦,谢谢!这是一个很好的解决方案,也很好的工作Lol,现在这个过程运行在1毫秒。谢谢!这是一个很好的解决方案,也可以很好地工作Lol,现在该过程在1ms内运行。Lmao