简体   繁体   English

如何有效地遍历大列表?

[英]How do I efficiently iterate through a big list?

I want to make a open world 2D Minecraft like game and have the world load in Chunks (just like MC) with a size of 16x16 blocks (a total of 256 blocks).我想制作一个像 Minecraft 这样的开放世界 2D 游戏,并在 Chunks 中加载世界(就像 MC 一样),大小为 16x16 块(总共 256 个块)。 But I found out through iterating 256 times that it takes almost 20ms to iterate completely with a code like this:但是我通过迭代 256 次发现,使用这样的代码完全迭代需要将近 20 毫秒:

long time = System.nanoTime();
for(int i = 0; i < 16*16; i++)
{
    System.out.println(i);
}
System.out.println(System.nanoTime() - time);

And since I'm not only going to print numbers but also get a block, get it's texture and draw that texture onto the frame, I fear it might take even longer to iterate.由于我不仅要打印数字,还要获取一个块,获取它的纹理并将该纹理绘制到框架上,我担心迭代可能需要更长的时间。 Maybe I just exaggerate a bit, but is there a way to iterate faster?也许我只是夸大了一点,但有没有办法更快地迭代?

It's not the iteration that takes 20ms, it's println();不是需要 20ms 的迭代,而是println(); . . The following will be much faster:以下将更快:

long time = System.nanoTime();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 16*16; i++)
{
    sb.append(i + System.getProperty("line.separator"));
}
System.out.println(sb);
System.out.println(System.nanoTime() - time);

So, first off, take into account that a list with 256 is not considered generally to have a big size.因此,首先,请考虑到通常不认为具有 256 的列表具有大尺寸。

The main thing consuming time your code is not iterating through the list but using System.out.println() .消耗代码时间的主要事情不是遍历列表而是使用System.out.println() Printing to console (or any I/O action) tends to take longer than other instructions.打印到控制台(或任何 I/O 操作)往往比其他指令花费更长的时间。

When I try your code locally I get roughly 6 ms but if I do something like this:当我在本地尝试你的代码时,我得到大约 6 毫秒,但如果我做这样的事情:

    long secondStart = System.nanoTime();
    StringBuffer stringBuffer = new StringBuffer();
    for(int i = 0; i < 16*16; i++)
    {
        stringBuffer.append(i);
        stringBuffer.append("\n");
    }
    System.out.println(stringBuffer);
    System.out.println(System.nanoTime() - secondStart);

I get 0.5ms.我得到 0.5 毫秒。

If that approach is not suitable for your needs then you would need to do as other comments say, consider traversing different parts of the list in parallel, maybe move to a different kind of traversal or even a different kind of structure.如果这种方法不适合您的需求,那么您需要像其他评论所说的那样做,考虑并行遍历列表的不同部分,可能转向不同类型的遍历甚至不同类型的结构。

Hope this helps.希望这可以帮助。

You should ask yourself if you really need to do all that work.您应该问问自己是否真的需要完成所有这些工作。 Do you need to draw things that are not seen by the camera for example?例如,您是否需要绘制相机看不到的东西? Of course not, so exclude every block in that chunk that is outside the camera rect.当然不是,因此排除该块中位于相机矩形之外的每个块。

Filtering out the blocks not seen implies some overhead but it is generally worth it compared to drawing every block in the chunk on each render update because drawing stuff is quite a heavy operation.过滤掉看不见的块意味着一些开销,但与在每次渲染更新时绘制块中的每个块相比,它通常是值得的,因为绘制内容是一项非常繁重的操作。

If you only want to speed up the traversal you could spawn threads that traverse the chunk in parallell or buy better hardware.如果您只想加快遍历速度,您可以生成并行遍历块的线程或购买更好的硬件。 But it is better to start with the question of how you could achieve the same result with less work put in.但是最好从如何以更少的工作量获得相同结果的问题开始。

On the other hand your computer should probably be able to draw 256 textures without problem especially if done on the gpu.另一方面,您的计算机应该能够毫无问题地绘制 256 个纹理,尤其是在 GPU 上完成时。 So maybe do some testing before making premature optimizations.所以也许在进行过早优化之前做一些测试。

PS.附注。 It isn't really the traversal itself you want to optimize for but rather the work done in each iteration.您真正想要优化的并不是遍历本身,而是每次迭代中完成的工作。 Just iterating 256 times is going to be quite fast.只需迭代 256 次就会非常快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM