Java中的高性能原始数组构建器
Posted
技术标签:
【中文标题】Java中的高性能原始数组构建器【英文标题】:High performance primitive array builder in Java 【发布时间】:2017-01-18 22:41:07 【问题描述】:我目前使用 google-or 工具来解决最大流量问题,所以这让我在 java 中创建了一些 int[] 数组以传递给 ortools。现在 ortools 非常快,在这里不是问题,但我对这里的性能替代品持开放态度。
问题主要在于构建数组,这需要大部分时间以及返回结果时的 GC,我将其归结为可能是 JNI 开销,而我对此无能为力。原始数组接近 5 - 700 万个点标记,它们大到足以要求它们是整数,短不是一种选择。我是否有任何选择或技巧,或者是否有人对如何最有效地构建这些有任何见解?内存在这里不是真正的问题我有足够的,并且在大多数情况下,我愿意接受任何解决方案以获得绝对前沿性能,即使它需要我的数据的不同表示,但这仍然必须能够插入 Ortools (除非 您有一个替换它的想法)但我欢迎任何关于如何从中获得最快阵列构建的建议。请注意,我不提前知道数组的长度,我不进行更新、删除,只追加。我很乐意提供更多细节。感谢您的任何建议。
【问题讨论】:
问题不清楚。如果您有性能问题,请分享您用来衡量性能的代码和方法。 既然你提到了JNI,那么使用直接缓冲区可能会更好,例如IntBuffer b = ByteBuffer .allocateDirect(size*Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer();
,这需要 JNI 代码才能处理它们。如果性能问题与 JNI 无关,则要么是逻辑错误,如 maaartinus’ answer describes,要么没有什么可改进的。
【参考方案1】:
评论太长了。
如果与解决问题相比,构建问题表示需要大量时间,那么您做错了什么。我猜,你正在使用类似的东西
int[] appendTo(int[] array, int element)
int[] result = Arrays.copyOf(array, array.length + 1);
result[result.length - 1] = element;
return result;
具有二次复杂度。该解决方案类似于ArrayList
所做的:按某个固定因子增长并忽略尾随数组元素。这可能不是您最终需要的,但是将所有数组缩小一次(就在将它们传递给库之前)很便宜。
你可以使用类似的类
class MyIntArray
private int length;
private int[] data = new data[4];
// This does the final shrinking.
public int[] toArray()
return Arrays.copyOf(array, length);
public MyIntArray append(int element)
if (array.length == length)
array = Arrays.copyOf(array, 2 * length);
array[length++] = element;
或滥用int[]
的最后一个元素来跟踪逻辑length
(效率稍高,但非常hacky)。
有各种权衡,例如,您可以使用 length + (length >> 1)
而不是 2 * length
将增长因子降低到 1.5,从更短或更长的数组开始,或者甚至使用空数组(如 ArrayList
; 那么你还需要调整生长因子)。
【讨论】:
以上是关于Java中的高性能原始数组构建器的主要内容,如果未能解决你的问题,请参考以下文章
为啥 UIImageView 在运行时从其原始位置(界面构建器)移动?
从原始 SQL 到 Laravel Eloquent 或查询构建器