Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Perl: Общие вопросы > переменная $_ |
Автор: Jilian 8.7.2008, 10:47 |
Добрый день! У меня было собеседование, но котором мне задали следующий вопрос. Как происходит распределение ПМ в перл и сколько занимает переменная $_ по умолчанию. Не могли бы вы дать мне пару статей на эту тему. Как-то этот вопрос не освящался ни в книгах, ни на форумах. Спасибо большое! |
Автор: arto 8.7.2008, 11:34 |
"ПМ в перл" -- ? |
Автор: Jilian 8.7.2008, 11:48 | ||
What is $_? How many memory taken this variable by default? Как вы понимаете, первый вопрос затруднений не вызвал, а вот второй.... |
Автор: ginnie 8.7.2008, 11:50 | ||
Уважаемый Jilian, по поводу размера $_ я тоже не знал. Судя по
Переменная занимает 12 байт (как и любой другой неинициализированный скаляр); |
Автор: amg 8.7.2008, 11:54 | ||
ginnie, опередил! |
Автор: Jilian 8.7.2008, 11:59 |
Спасибо всем большое. =) Теперь буду знать, что отвечать на такие вопросы =) |
Автор: ginnie 8.7.2008, 12:01 |
Jilian, подобных вопросов придумать можно еще много. Простых: размер пустого массива или хеша, и сложных: из чего этот размер складывается ![]() |
Автор: Jilian 8.7.2008, 12:09 |
В компании нужен был человек, который мог бы написать пару несложных скриптов на перле. Кастомеры попались странные, спрашивали как представить строку из китайских иероглифов и всякое в этом роде, так что вопрос с переменной $_ еще был нормальным =) А где можно почитать про то, как складывается размер переменных в перле? |
Автор: tolkien 8.7.2008, 12:11 |
ИМХО вопрос не корректный. Т.к распределение памяти скрыто от программиста. И им занимается только сам Perl. И размер соотвественно скалярных переменных содержащих одно и тоже может быть разным в разных версиях Perl. |
Автор: amg 8.7.2008, 12:21 |
По моему, более актуальным был бы вопрос "Сколько занимает минимальный элемент хэша?", потому как часто случается, что на хэш из 20 М элементов гига памяти вдруг не хватает. (У меня получилось 39 байт). |
Автор: ginnie 8.7.2008, 12:51 |
Уважаемый amg, не подскажите, как связан вопрос "Сколько занимает минимальный элемент хэша?" с "потому как часто случается, что на хэш из 20 М элементов гига памяти вдруг не хватает"? |
Автор: Jilian 8.7.2008, 14:20 |
2 amg А не подскажите, с чем связана необходимость прибавления этого числа? |
Автор: AlexPet 8.7.2008, 15:42 | ||
ginnie, если не сложно, не могли бы сами прокомментировать эти вопросы? ![]() |
Автор: ginnie 8.7.2008, 16:45 | ||
Много интересного можно прочитать в http://books.simon-cozens.org/index.php/Perl_5_Internals. AlexPet, вопросы я написал по аналогии с заданным про размер $_. Смысл они имеют, разве что при поиске хорошего разработчика XS-модулей или Perl-хакера ![]() Сами по себе подобные знания мало что дают (кроме осознания собственной "крутизны"), важно выяснить умение их использования соискателем для решения реальных задач. |
Автор: AlexPet 8.7.2008, 17:26 |
ginnie, полностью с Вами согласен. Просто подумал, а вдруг что-то упустил, какую-нибудь интересную мелочь? ![]() |
Автор: amg 9.7.2008, 14:40 |
Поигрался с модулем Devel::Size, заодно провел небольшое исследование о памяти, занимаемой различными структурами. Использовал функцию 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 байта на каждый элемент. Пример того, что хэшами нужно пользоваться с осторожностью Стандартная задача: организовать быстрый доступ к элементам массива (не по номеру, а по значению). Используют преобразование массива в хэш. Массив из миллиона целых чисел [1..1000000] занимает в памяти очень умеренные по нынешним временам 20 М. Хэш {map {$_=>""} 1..1000000}, полученный из этого массива, занимает 410 М. Уже опасно даже по нынешним временам. Использование в качестве значений хэша undef вместо пустой строки "" помогает, но не спасает (экономит лишь 16 М; основное место, 320 М, в этом хэше занимают не данные, а сама структура). _____________________________ PS Все эти формулы я толком не тестировал, может, они и неправильные. Очевидно, будет зависимость от архитектуры машины и, возможно, от версии Perl (у меня - linux x32, perl 5.8.8) _____________________________ PPS Что-то я туплю. Как проще вычислить для числа ближайшую к нему (снизу) степень двойки? (вместо того, что у меня 2**(length(sprintf("%b",$n))) ) |
Автор: AlexPet 9.7.2008, 14:49 | ||||
Если делать по стандарту, то
Но не думаю, что будет сильный выигрыш во времени ![]() |
Автор: amg 9.7.2008, 15:01 |
Вначале я и использовал выражение с логарифмами, но потом тоже решил, что со sprintf быстрее будет. Но все равно не нравится. Кажется мне, что какой-нибудь pack/unpack здесь будет уместен, но я эти функции плохо знаю. |
Автор: Jilian 10.7.2008, 10:36 |
Вы знаете, только что услышала мнение одного специалиста в перл, что изначально переменная $_ занимает все свободную память. |
Автор: amg 10.7.2008, 12:13 | ||
|
Автор: Bulat 10.7.2008, 18:56 | ||
Хм.. думаю будет по сабжу. Давно интересовал такой вопрос. При использовании регулярных выражений, и некоторых функций работающих со строковыми данными, например,
В данном случае, для того чтобы вытащить из строки некоторую его часть с помощью регулярного выражения, память расходуется ровно, или приблизительно, в два раза больше чем память занимаемая $1. Есс-но я не имею ввиду занимаемую память, в которой хранится весь текст($text). Поэтому при работе с большими текстами, советуют делить строковые данные на более мелкие части, например, построчно. Все никак не рожу, чтоб поискать и почитать про причины такого поведения. |
Автор: amg 11.7.2008, 05:07 |
При этом еще переменныя $+ заполняется тем же самым. |
Автор: Ramirez 19.8.2008, 16:48 | ||||||
Во многих случаях хеши можно заменить массивами. Можно даже "изобразить" доступ по ключу для удобства:
хотя, зачастую вместо констант используется такая конструкция:
http://www.perl.com/doc/manual/html/pod/perlsub.html#Constant_Functions в http://www.perl.com/doc/manual/html/lib/constant.html пишут, что: In the current implementation, scalar constants are actually inlinable subroutines. As of version 5.004 of Perl, the appropriate scalar constant is inserted directly in place of some subroutine calls, thereby saving the overhead of a subroutine call. See Constant Functions for details about how and when this happens. Интересно, как сейчас с этим обстоят дела. Если константа это функция, это ведь оверхед получается неслабый... попробовал
У меня массив из 1000 элементов занимал 24 килобайта, а хеш - 52 килобайта. Т.е. хеш в 2 раза дороже. Если использовать массив с константами в качестве "индексов" то к массиву плюс 20 * 1000 = 20 килобайт займут константы. Итого размер массива + константы примерно будет равен хешу, что сведет преимущества к нулю. Преимущества от массива с константами перед хешем будет если используется одновременно много таких массивов, т.к. константы/индексы будут общие на все массивы. |
Автор: sir_nuf_nuf 19.8.2008, 17:35 | ||
Ramirez, оверхеда как раз не получается, на этапе компиляции perl делает локальные оптимизации, вычисляя константы.. собственно говоря, если вы напишите что то вроде:
это будет вычислено 1 раз при компиляции, а результат будет подставлен во все вызовы.. |