写一个需要做很多比较的游戏,它很滞后。我正在试着加速它,这段代码每一帧都要运行数千次,对于不同的xy和z值。有没有更好的方法来检查数组中xy和z的值是否有效?(java)第一个月我试过检查blocksArr[x][y][z]!是否为null,也试过检查blocksArr[x][y][z]!是否为undefined,但都没有给予结果。
ntjbwcob1#
你所做的是边界检查,以确保索引x,y和z是blocksArr[][][]数组中的有效索引,在C中,这是必要的,因为C允许你到数组之外。然而,Java在每次访问数组时都会进行边界检查,所以你要手动进行边界检查,然后再进行一次检查,再加上Java在二维空间进行检查,最后Java在三维空间进行检查。您真正需要做的只是访问数组,让Java进行边界检查,如果任何索引超出边界,则捕获异常。
x
y
z
blocksArr[][][]
boolean value; try { value = blocksArr[x][y][z]; } catch (ArrayIndexOutOfBoundsException e ) { value = false; }
设置try/catch块会有一些开销,但总体上应该会更快。
omvjsjqw2#
一般来说,在u已知为正的情况下,计算t >= 0 && t < u的最有效方法是使用Integer.compareUnsigned(t, u) < 0比较t和u的无符号值。
u
t >= 0 && t < u
Integer.compareUnsigned(t, u) < 0
t
if (Integer.compareUnsigned(x, blocksArr.length) < 0 && Integer.compareUnsigned(y, blocksArr[x].length) < 0 && Integer.compareUnsigned(z, blocksArr[x][y].length) < 0 && blocksArr[x][y][z])
但是,我认为您将blocksArr表示为三维数组的效率非常低,并且会导致大量间接操作,这极大地阻碍了潜在的性能。一个更合理的方法是将其表示为单个数组,并将长度、宽度和高度分别存储。这将导致您的代码看起来像这样:
blocksArr
if (Integer.compareUnsigned(x, length) < 0 && Integer.compareUnsigned(y, width) < 0 && Integer.compareUnsigned(z, height) < 0 && blocksArr[x * (width * height) + y * height + z])
然而,这限制了你的块大约20亿个元素,为了克服这个限制,你需要求助于内存访问API,它目前正在预览中。它有一个重要的优势,它允许内存块的分配和释放是确定的,这是太大的内存块更可取的。使用内存段来表示blocksArr,你的代码将成为:
if (Long.compareUnsigned(x, length) && Long.compareUnsigned(y, width) && Long.compareUnsigned(z, height) && blocksArr.get(ValueLayout.JAVA_BOOLEAN, x * (width * height) + y * height + z))
此外,由于blocksArr是一个布尔值块,将其打包,使每个元素仅占1位,将大大改善内存消耗和缓存压力,现在的检查可以表示为:
long index = x * (width * height) + y * height + z; long byteIndex = index >>> 3; int shift = (int)(index & 7); if (Long.compareUnsigned(x, length) && Long.compareUnsigned(y, width) && Long.compareUnsigned(z, height) && blocksArr.get(ValueLayout.JAVA_BYTE, byteIndex) & (1 << shift) != 0)
blmhpbnm3#
我不懂java,但总的来说,我希望下面的代码至少和java一样快,可能更快。你的编译器可能会做类似的事情,所以它可能不会更快。你可以把“If”语句分开,这样它会做更少的查找。对不起,我必须把它写成c代码。你可以理解这个想法,然后翻译成java。
if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length) { if (y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) { ..... } }
假设user16320675关于求值顺序是正确的,你可以使用一个if语句,我不知道java编译器是如何工作的。
if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length && y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) .....
3条答案
按热度按时间ntjbwcob1#
你所做的是边界检查,以确保索引
x
,y
和z
是blocksArr[][][]
数组中的有效索引,在C中,这是必要的,因为C允许你到数组之外。然而,Java在每次访问数组时都会进行边界检查,所以你要手动进行边界检查,然后再进行一次检查,再加上Java在二维空间进行检查,最后Java在三维空间进行检查。
您真正需要做的只是访问数组,让Java进行边界检查,如果任何索引超出边界,则捕获异常。
设置try/catch块会有一些开销,但总体上应该会更快。
omvjsjqw2#
一般来说,在
u
已知为正的情况下,计算t >= 0 && t < u
的最有效方法是使用Integer.compareUnsigned(t, u) < 0
比较t
和u
的无符号值。但是,我认为您将
blocksArr
表示为三维数组的效率非常低,并且会导致大量间接操作,这极大地阻碍了潜在的性能。一个更合理的方法是将其表示为单个数组,并将长度、宽度和高度分别存储。这将导致您的代码看起来像这样:然而,这限制了你的块大约20亿个元素,为了克服这个限制,你需要求助于内存访问API,它目前正在预览中。它有一个重要的优势,它允许内存块的分配和释放是确定的,这是太大的内存块更可取的。使用内存段来表示
blocksArr
,你的代码将成为:此外,由于
blocksArr
是一个布尔值块,将其打包,使每个元素仅占1位,将大大改善内存消耗和缓存压力,现在的检查可以表示为:blmhpbnm3#
我不懂java,但总的来说,我希望下面的代码至少和java一样快,可能更快。你的编译器可能会做类似的事情,所以它可能不会更快。你可以把“If”语句分开,这样它会做更少的查找。对不起,我必须把它写成c代码。你可以理解这个想法,然后翻译成java。
假设user16320675关于求值顺序是正确的,你可以使用一个if语句,我不知道java编译器是如何工作的。