Какая польза preallocating памяти для массива в perl?

Perl позволяет использовать предварительно распределенные массивы. Мы можем предварительно выделить массив перед использованием, тогда мы можем добавить еще несколько элементов. Например, выделение 50 элементов массива, а затем добавление 51-го элемента, поскольку массивы расширяемы. Таким образом, предварительное распределение массива повышает производительность?

Ответ 1

Из-за того, как память распределяется на компьютерах. Память компьютера подобна пространству на доске: она имеет положение относительно другой памяти; и он не может быть перемещен, он должен быть скопирован.

Если вы создадите небольшой массив, он может выглядеть так:

@array = (1, 4, 8, 12, 19);

allocate memory for @array
______________________|               |______| a b c|__________

copy in the data
______________________|  1  4  8 12 19|______| a b c|__________

_ - нераспределенная память. | указывает границы того, что выделяется вашему массиву. | a b c| - это еще один массив.

Затем, если вы несколько раз нажмете на этот массив, Perl придется перераспределять память. В этом случае он может увеличить память, которую он уже имеет в нераспределенном пространстве.

push @array, 23, 42;

grow the existing memory
______________________|  1  4  8 12 19      | a b c|__________

add the new data
______________________|  1  4  8 12 19 23 42| a b c|__________

Теперь, что произойдет, если вы нажмете больше чисел на @array? Он больше не может вырастить вашу память, есть еще один массив. Таким образом, как и на доске, он должен скопировать весь массив в ясный кусок памяти.

push @array, 85, 99;

Allocate a new chunk of memory
|                           |  1  4  8 12 19 23 42| a b c|__________

Copy the existing data
|  1  4  8 12 19 23 42      |  1  4  8 12 19 23 42| a b c|__________

Deallocate the old memory
|  1  4  8 12 19 23 42      |__1__4__8_12_19_23_42| a b c|__________

Add the new data
|  1  4  8 12 19 23 42 85 99|__1__4__8_12_19_23_42| a b c|__________

Чтобы сэкономить время, Perl не хочет стирать старые данные. Он просто освободит его, и что-то еще может нацарапать его, когда им нужно.

Это делает push более дорогим, особенно с очень большими массивами, которые должны копировать больше данных. По мере увеличения вашего массива все больше и больше вероятность, что Perl придется выделять свежий кусок памяти и копировать все.

Есть еще одна проблема: фрагментация памяти. Если вы распределяете и перераспределяете снова и снова, куски памяти могут быть нарезаны, поэтому трудно найти большие блоки свободной памяти. Это проблема не только для современных операционных систем, но и для беспокойства. Может показаться, что у вас меньше памяти, чем у вас на самом деле, и это может привести к тому, что операционная система будет использовать диск в качестве памяти (виртуальной памяти) больше, чем нужно. Диски медленнее памяти.


Я упростил многое. Я сделал вид, что Perl должен перераспределять каждый раз, когда вы push. Это неверно. Perl выделяет больше памяти для массивов, чем нужно именно по этой причине. Таким образом, вы можете смело добавить несколько дополнительных записей в массив без перераспределения Perl. То же самое относится к строкам и хэшам.

Другое дело - это, вероятно, несколько устаревшее представление о том, как распределение памяти работает на современных операционных системах... хотя Perl иногда выполняет собственное распределение памяти, если не доверяет ОС. Проверьте use Config; print $Config{usemymalloc}. n указывает, что Perl использует выделение памяти операционной системы, y указывает на использование Perl.

Эмпирическое правило: не предопределяйте, это, вероятно, пустая трата времени и памяти компьютера. Однако, если все приведенные ниже условия верны, посмотрите, помогает ли предварительное распределение.

  • Вы профилировали и обнаружили проблему.
  • Вы постепенно наращиваете структуру данных, добавляя к ней.
  • Вы точно знаете минимальный возможный размер.
  • Этот размер "большой".

Что такое "большой", для обсуждения и зависит от вашей версии Perl, вашей операционной системы, вашего оборудования и вашей производительности.