java – 大型小对象的慢速初始化
我今天偶然发现了这个案子,我想知道这个巨大差异背后的原因是什么.
第一个版本初始化一个5k x 5k的raw int数组: public void initializeRaw() { int size = 5000; int[][] a = new int[size][size]; for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) a[i][j] = -1; } 我的机器大约需要300毫秒. public class Struct { public int x; public int y; } public void initializeStruct() { int size = 5000; Struct[][] a = new Struct[size][size]; for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) a[i][j] = new Struct(); } 花费超过15000ms. 我希望它有点慢,毕竟有更多的内存要分配(如果我没有弄错的话,10个字节而不是4个字节),但我不明白为什么它需要花费50倍的时间. 有人能解释一下吗?也许只有更好的方法来进行Java中的这种初始化? 编辑:对于一些比较 – 使用Integer而不是int / Struct的相同代码工作700ms – 只慢两倍. 解决方法
当您创建5000个int的数组时,您将一次性分配所有这些整数所需的所有空间,作为单个连续元素块.为每个数组元素分配一个int时,您没有分配任何内容.与5000个Struct实例的数组形成对比.您遍历该数组,并为这5000个元素中的每一个元素分配一个Struct实例.分配对象比简单地将int值写入变量需要花费更长的时间.
你有二维数组的事实在这里没有太大的比较差异,因为它只是意味着你在两种情况下都分配5000个数组对象. 如果要对一组Integer对象进行计时,然后将每个元素设置为-1,那么每次都不会分配单独的Integer对象.相反,您正在使用自动装箱,这意味着编译器隐式调用Integer.valueOf(-1),并且该方法每次都从缓存中返回相同的对象. 更新:回过头来解决您的问题,如果我理解正确,您需要将5000×5000 Structs保留在2D数组中,并且您对创建此数组比使用原语需要更长时间感到失望.为了提高性能,您可以创建两个基元数组,一个用于Struct的每个字段,但这会降低代码清晰度. 你也可以创建一个long数组(因为每个long的长度是int的两倍)并使用&和>>操作符获得原始的整数.同样,这会降低代码清晰度,但是你只有一个数组. 但是,您似乎专注于代码的单个部分,即数组的创建.您可能会发现,对每个元素执行的处理会使创建数组所花费的时间过多.分析整个应用程序,看看阵列的创建是否重要. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |