Иногда (мне -- довольно часто) требуется оценить, сколько оперативной памяти займет большая структура Perl (особенно это актуально для хэшей). Документации по этоиу поводу я не нашел, поэтому провел собственное небольшое исследование.
Простой пример, зачем это нужно.
Стандартная задача: организовать быстрый доступ к элементам массива (не по номеру, а по значению). Используют преобразование массива в хэш.
Массив из миллиона целых чисел [1..1000000] занимает в памяти очень умеренные по нынешним временам 20 М.
Хэш {map {$_=>""} 1..1000000}, полученный из этого массива, занимает 410 М. Уже опасно даже по нынешним временам. Использование в качестве значений хэша undef вместо пустой строки "" помогает, но не спасает (экономит лишь 16 М; основное место, 320 М, в этом хэше занимают не данные, а сама структура).
Ниже приведены формулы, позволяющие провести оценку количества оперативной памяти, необходимого для структуры заранее известного размера.
Использовал функцию size() модуля Devel::Size, подсчитывающую память, занимаемую самой структурой (в случае нескаляров -- без данных). В модуле есть еще функция total_size() (память для структуры вместе с данными), но она глючит на хэшах. Вот результаты:
undef
12 b
Целые числа
0-4294967296 (2**32) 16 b, далее 20 b
Числа с floating point
20 b
Строки
28 + $n - $n%4
($n - длина строки)
Массивы
Анонимный массив
56 + @$aref*4 + $data
(@$aref - число элементов массива, $data - суммарный объем данных, вычисляемый по предыдущим формулам)
Именованный массив
Почему то все сложнее, четкой закономерности я не обнаружил, но приближенно верна формула для анонимного массива
В первом приближении -- данные + 4 байта на каждый элемент
Хеши
Совсем все сложно
(92 + (22+length($key))*$n + 2**(length(sprintf("%b",$n))+2)-32) + $data
Это приближенная формула (в некоторых случаях она не дает точное значение).
length($key) - длина ключа хэша (я использовал ключи одинаковой длины, для прикидок можно брать среднюю длину ключа, или максимальную, чтобы с запасом), $n - число элементов хэша (пар ключ-значение), $data - суммарный объем данных (ключи + значения; при вычислении нужно помнить, что ключи, как оказалось, если они числа, автоматически превращаются в строки и памяти занимают больше).
В нулевом приближении -- данные + 32 байта на каждый элемент.
PS Эти формулы я толком не тестировал. Возможно, будет зависимость от архитектуры машины и от версии Perl (у меня - linux x32, perl 5.8.8)
