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中的高性能原始数组构建器的主要内容,如果未能解决你的问题,请参考以下文章

php 布局构建器中的facetwp数组处理

将原始 SQL 查询传递给 Laravel 上的查询构建器

为啥 UIImageView 在运行时从其原始位置(界面构建器)移动?

从原始 SQL 到 Laravel Eloquent 或查询构建器

如何使用 Laravel 的流畅查询构建器混合原始 SQL 和非原始 SQL

java调用构建器如何将响应作为字符串进行记录?