分配数组需要多长时间(用Java)

时间:2013-08-11 19:36:45

标签: java arrays

关于数组分配的一般性问题,主要是在Java中,但我认为它与所有编程语言相关:

为大小为n的数组[以O(n)为单位)分配内存需要多长时间?我可以想象一个实现,其中内存分配在恒定时间内发生:如果你有大量的空内存你可以创建一个指向新数组的第一个和最后一个索引的指针,但是通常如何分配内存? (另外,至少在Java中,如果初始化整数数组,则数组中的所有值最初都设置为0;这是否意味着数组中的每个索引都单独设置为等于0,这将进行操作O(n)?)

感谢。

3 个答案:

答案 0 :(得分:9)

我刚刚在热点上运行micro benchmark - 发布JIT编译,分配一个数组(在i7上)需要:

  • 对于大小为1的数组
  • 大约10 ns
  • 对于大小为10,000的数组
  • ,大约400 ns
  • 对于大小为1,000,000
  • 的数组,大约300,000 ns

所以为了回答你的问题,根据经验证明它在热点上是O(n)

详细结果:

Benchmark                              Mode Thr    Cnt  Sec         Mean   Mean error    Units
c.a.p.ArrayVsList.createArray1         avgt   1      5    2       12.293        0.867  nsec/op
c.a.p.ArrayVsList.createArray10000     avgt   1      5    2      428.369        9.997  nsec/op
c.a.p.ArrayVsList.createArray1M        avgt   1      5    2   342972.975     7253.989  nsec/op
  • 在java中创建一个对象,如果你的堆足够大,几乎是免费的(它大致包括偏移一个指针)
  • 但是JVM似乎在创建数组时急切地将所有项初始化为null(或者对于基元为0)
  • 其他JVM可能会执行更新的lazier

答案 1 :(得分:3)

你已经自己回答了这个问题,因为元素是初始化的,所以在Java中它是O(n),而有些语言的操作是O(1),因为没有初始化。

只是为了确定

public class ArrayTest {

  public static void main(String[] args) {
     int[] var = new int[5];
  }

}

产生

public class ArrayTest extends java.lang.Object{
public ArrayTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_5
   1:   newarray int
   3:   astore_1
   4:   return

}

和文档说明 newarray

  

一个新数组,其组件的类型为atype,长度为count   从垃圾收集堆中分配。引用arrayref到   这个新的数组对象被推入操作数堆栈。 每个   新数组的元素初始化为默认初始值   对于数组的类型(§2.5.1)。

答案 2 :(得分:3)

AFAIK,阵列分配总是O(n),直到你可以拥有的最大尺寸。这是因为将存储器清零的成本也是O(n)。系统可以采取一些技巧来加快速度。即它不必将每个字节清零,它可以使用一些虚拟内存技巧将整个页面清零,但即便如此,这也是O(n)。