Подтвердить что ты не робот

Сколько времени занимает выделение массива (в Java)

Просто общий вопрос о распределении массива, прежде всего в Java, но я думаю, что он имеет отношение ко всем языкам программирования:

Сколько времени занимает выделение памяти для массива размером n [в терминах O (n)]? Я мог представить себе реализацию, в которой распределение памяти происходит в постоянное время: если у вас есть большое количество пустой памяти, вы можете просто создать указатель на первый и последний индекс нового массива, но так ли, как обычно выделяется память? (Кроме того, по крайней мере, на Java, если вы инициализируете массив целых чисел, все значения в массиве с исходным значением равны 0, означает ли это, что каждый из индексов в массиве индивидуально установлен равным 0, что сделать операцию O (n)?)

Спасибо.

4b9b3361

Ответ 1

Я просто запустил микро-тест в компиляции JIT-hotspot-post, выделение массива (на i7) занимает:

  • около 10 нс для массива размером 1
  • около 400 нс для массива размером 10 000
  • около 300 000 нс для массива размером 1 000 000

Итак, чтобы ответить на ваш вопрос, , кажется эмпирически, что это O (n) на hotspot.

Подробные результаты:

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 могут выполнять более ленивую инициализацию

Ответ 2

Вы уже ответили на вопрос самостоятельно, это O(n) в Java, поскольку элементы инициализированы, в то время как существуют языки, где эта операция 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 и счетчик длины выделенных из собранной мусором кучи. Референтный массив для этот новый объект массива помещается в стек операнда. Каждыйэлементы нового массива инициализируются исходным значением по умолчаниюдля типа массива (п. 2.5.1).

Ответ 3

AFAIK, распределение массива всегда равно O (n) до максимального размера, который вы можете иметь. Это связано с тем, что стоимость обнуления памяти равна O (n). Есть несколько уловок, которые система может сделать, чтобы сделать это быстрее. т.е. ему не нужно обнулять каждый байт, он может обнулить целые страницы, используя некоторые трюки с виртуальной памятью, но даже это также O (n).