![]() |
|
Модераторы: korob2001, ginnie |
![]()
|
|
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Уважаемые коллеги!
Допустим в коде есть функция test_func():
Нужно удостовериться, что память, занимаемая значениями $value_1 и $value_2 (пусть значения будут длинными, например 500Кб) по окончании вызова функции освобождается (чтобы исключить подозрение, что интерпретатор выделяет память для локальной переменной и не помечает ее как свободную между вызовами). Хотел бы услышать Ваши предложения по такому тесту. Это сообщение отредактировал(а) ginnie - 11.4.2008, 21:25 -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| KSURi |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
Может просто попробовать задать значения по 10-20 мегабайт (чтобы невооруженным взглядом было видно) и промониторить память внешней утилитой (top, taskmanager)?
Добавлено через 1 минуту и 13 секунд в смысле память занимаемую конкретно perl'вым процессом -------------------- Died at Life.pl line 21 |
|||
|
||||
| GoDleSS |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
Если мне не изменяет память, то как раз в данном случае память и не будет высвобождаться и переменные будут занимать масимальный объем из всех вызовов. Так что если этот момент критичен - лучше андефить. --------------------
It's a nice day to die my friend! |
|||
|
||||
| BurnerCode |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 28.2.2008 Где: Беларусь Репутация: нет Всего: нет |
А мне кажеться что память высвобадиться, ведь эти 2е переменные уничтожаются при выходе из ф-ции.
|
|||
|
||||
| GoDleSS |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
BurnerCode, почитайте пожалуйста тему http://forum.vingrad.ru/forum/topic-201623/view-all.html
--------------------
It's a nice day to die my friend! |
|||
|
||||
| Bulat |
|
|||
![]() татарский Нео ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1701 Регистрация: 22.3.2006 Где: Альметьевск Репутация: 5 Всего: 57 |
Насколько я помню, бывало так, что никакие тесты, вообще что-то тривиальное не помогало мне высвобождать память, даже тот же андеф. В случае с большими строками, лучше разбивать все это где нить по 32Kb и работать спокойно.
-------------------- менеджер по кодеврайтингу |
|||
|
||||
| ginnie |
|
||||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Информация для обсуждения:
тестовый скрипт
результат теста (один из результатов, цифры меняются)
теперь раскомментирую строки undef в функциях test_func() и test_func2()
Похоже на то, что если явно не делать undef для переменных в функции, то память, занятая переменной не освобождается на случай повторного использования. Если переменным делать undef, то память освобождается. Это сообщение отредактировал(а) ginnie - 10.4.2008, 11:48 -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
||||||
|
|||||||
| KSURi |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
По логике так и должно быть имхо...
Кстати, хотелось бы уточнить: если делать $var = undef, а не undef $var, то память вроде не будет освобождаться. ginnie, если у вас уже есть готовые тесты, не могли бы попробовать такой вариант? -------------------- Died at Life.pl line 21 |
|||
|
||||
| ginnie |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Тест с использованием
-------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
||||
|
|||||
| KSURi |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
Как я и думал)
-------------------- Died at Life.pl line 21 |
|||
|
||||
| ginnie |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Не нравится еще вот это:
Как мне было хорошо, когда я этого не знал! -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
||||
|
|||||
| KSURi |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
Ну и в очередной раз имхо все логично... Вы просто 3 раза скопировали $test.
А вот если будет так:
то такого результата не будет. Во всяком случае я так думаю) -------------------- Died at Life.pl line 21 |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
KSURi, обращаю Ваше внимание на проблему: она в том, что в примере есть блок if, внутри которого создается локальная переменная и память, занимаемая этой переменной не освобождается после выхода из блока.
В приведенных примерах я копирую несколько раз большой фрагмент для того, чтобы увидеть, освобождается память или нет. Других способов я не знаю. Изначально у нас есть переменная $test, которая содержит текст 1000000 байт. Далее попадаем в блок if внутри которого создается локальная переменная и инициализируется длинным текстом. По окончании блока переменная уничтожается и память должна освободится (общий объем памяти, используемой скриптом не уменьшается, т.к. интерпретатор свободную память системе не возвращает). Чтобы понять, освободилась память или нет, надо создать еще одну переменную и присвоить ей длинный текст. Если общий объем памяти увеличился - значит при выходе из блока память не освобождается. Добавлено через 6 минут и 18 секунд Для уменьшения используемой скриптом памяти (особенно это важно для mod_perl, который я постоянно использую) необходимо в конце использования переменной (массива, хеша) явно делать undef, что мне очень не нравится. -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| GoDleSS |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
Только в конце пакетов и подпрограмм. А также в том случае, если на эти переменные/массивы/хеши/и т.д. остались ссылки. --------------------
It's a nice day to die my friend! |
|||
|
||||
| BurnerCode |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 37 Регистрация: 28.2.2008 Где: Беларусь Репутация: нет Всего: нет |
оригинал тут: http://xpoint.ru/know-how/Perl/UtechkiPamyati?5
Модули: * Devel::Leak::Object - Специально для объектно-ориентированных программ, но просто незаменим. Наверное самое большое преимущество этого модуля в возможности отслеживать как все классы, так и отдельную группу. Модуль переопределяет функцию bless и DESTROY, а при выходе из программы выдает список объектов, которые не были уничтожены и трассировку стека в том месте программы, где объект был создан. Дальше обычно много легче самому проверить логику программы от точки создания объекта. Для работы всех этих вкусностей нужны патчи: http://rt.cpan.org/Ticket/Display.html?id=21145. Есть еще глюки и дока не очень, нокод pure perl и не очень сложный * Devel::Cycle - принимает ссылку и ищет циклы внутри. Полезно, когда вы знаете, что цикл внутри, но не найдет проблему если кто-то ссылается на этот объект снаружи. o Test::Memory::Cycle - несколько простых функци для использования в тестах на утечки памяти (использует Devel::Cycle). После того как вы избавились от цкилических ссылок в какой-то группе структур в вашей програме, вы пишете несколько тестов, которые проверябт что это так, что позволит вам быть частично уверенным, что больше этого не повторится. * Devel::FindRef - неплохой модуль, хоть и немного сыроват, но может помочь найти ссылки на объект, когда вы точно знаете, что объект не уничтожается, а внутри цикла нет. Например вы сохранили ссылку в глобальной переменной пакета. Это модуль можно использовать для написания модуля поиска циклов в переменных, которые ссылаются на текущую структуру. * Devel::Monitor * Object::Destroyer * Devel::ObjectTracker * Devel::GC::Helper * Devel::Leak * Devel::LeakTrace, Devel::LeakTrace::Fast - эти два модуля использую возможность perl устанавливать дополнительный обработчик на каждый оператор, что достаточно сильно замедляет выполнение, но позволяет отследить все на самом низком уровне. Второй модуль и правда быстрее так как на большом проекте я (Руслан) просто не дождался запуска сервера с первым модулем, но все равно скорость оставляет желать лучшего. * Devel::Size * Devel::DumpSizes * Devel::Size::Report * Devel::Arena Это сообщение отредактировал(а) BurnerCode - 11.4.2008, 08:38 |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Уважаемый BurnerCode все приведенные модули помогают избавиться от циклических ссылок. В контексте данного топика они бесполезны.
Это сообщение отредактировал(а) ginnie - 11.4.2008, 11:15 -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| tolkien |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 277 Регистрация: 5.4.2008 Репутация: 4 Всего: 4 |
Память не освобождается при выходе из любого блока или только if?
Если блок if поместить в бесконечный цикл? Память закончится? |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
Уважаемый tolkien, похоже, что не освобождается при выходе из любого блока.
При использовании блока внутри цикла память не освобождается, но повторно используется для тех-же самых переменных, поэтому она не может закончится. -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| tolkien |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 277 Регистрация: 5.4.2008 Репутация: 4 Всего: 4 |
Получается Perl вобще память не освобождает в процессе работы?
|
|||
|
||||
| GoDleSS |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
Высвобождает, но:
1. Память, выделенную для блоков резервирует под повторное использование. 2. Не удаляет те элементы, на которые сохранились ссылки. --------------------
It's a nice day to die my friend! |
|||
|
||||
| shamber |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1422 Регистрация: 5.9.2006 Где: Россия Репутация: 17 Всего: 18 |
ginnie, потестил Ваш код под win32. Как и следовало ожидидать результат тот же. |
|||
|
||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
GoDleSS, выделенную не для блоков, а для конкретных переменных (т.е. если в блоке две переменные и под одну выделилось 1 Мб, то в следующем проходе при записи во вторую переменную текста в 1 Мб будет дополнительно выделено 1 Мб)! Добавлено @ 14:40 Вчера выяснил, что эти проблемы с памятью (кроме блоков if), а также многие другие описал Даниил Алиевский в статье "Эффективное использование памяти в Perl при работе с большими строками", опубликованной в журнале Системный администратор в октябре 2002. Это сообщение отредактировал(а) ginnie - 11.4.2008, 15:04 -------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| GoDleSS |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
Полностью согласен, но не всегда четко выражаю свои мысли ((
Кстати, давным давно читал, занятная статейка в плане оптимизации ) --------------------
It's a nice day to die my friend! |
||||
|
|||||
| sir_nuf_nuf |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 920 Регистрация: 6.1.2008 Репутация: 14 Всего: 31 |
Кстати в той забавной статье написано, что
т.к. при этом для вычисления выражения конкатенации будет выделена память, которую потом нельзя освободить. т.е. я правильно понимаю, что очень_длинная_строка будет отъедать память трижды: в $very_long_text, в выражении $very_long_text . "\n" и в $v ? разве при присваивание переменной выражения память от выражения не освобождается ? (обычный стек) P.S. (to KSURi & co.) Есть какой-нть модуль что бы посмотреть дерево операций ( байт-код т.е.) которое перл строит по выражению ? |
|||
|
||||
| KSURi |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 887 Регистрация: 8.6.2006 Где: Russia Репутация: 20 Всего: 27 |
-------------------- Died at Life.pl line 21 |
||||
|
|||||
| ginnie |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1287 Регистрация: 6.1.2008 Где: Москва Репутация: 38 Всего: 49 |
sir_nuf_nuf, посмотри модуль B::Concise. Я, правда, пока еще сам с ним не разобрался до конца.
-------------------- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг) |
|||
|
||||
| tolkien |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 277 Регистрация: 5.4.2008 Репутация: 4 Всего: 4 |
есть разница по ресурсам писать так? my $v = $very_long_text . "\n"; или так my $v = "$very_long_text\n"; |
||||
|
|||||
| GoDleSS |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 105 Регистрация: 11.2.2007 Где: Пироговский Репутация: 2 Всего: 2 |
Практически нет, в обоих случаях будет использовано: память от $very_long_text+ память от "\n"(незначительно) + память, занимаемая объедененной строкой. А вот при print ... лучше использовать print $very_long_text, "\n"; т.к. тут получается 2 раздельных параметра и в случае print $very_long_text, "\n"; занимаемая память удвоится, а в случае print "$very_long_text\n"; утроится Вот такая бяка.... --------------------
It's a nice day to die my friend! |
|||
|
||||
| gcc |
|
||||||||
![]() Агент алкомафии ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2691 Регистрация: 25.4.2008 Где: %&й Репутация: 1 Всего: 17 |
кстате, вот увидел, кто как пишет и как правильно?
|
||||||||
|
|||||||||
| DaemonSuw |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 155 Регистрация: 11.3.2008 Репутация: 3 Всего: 3 |
По моему правильно так
Этот вариант без все равно что 'SELECT fullname FROM people WHERE $sql_clause' - без интерполяции gcc, "тест освобождения памяти, хочу убедиться, что память освобождается" - но почему вопрос в этом топике? |
||||
|
|||||
| gcc |
|
|||
![]() Агент алкомафии ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2691 Регистрация: 25.4.2008 Где: %&й Репутация: 1 Всего: 17 |
давно хотел спросит, просто не актуально было тут обсуждается как правильно писать переменные в тесте... тут можно написать и так наверное my $v = qq{$very_long_text \n}; |
|||
|
||||
| Ramirez |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 305 Регистрация: 18.1.2005 Где: Moscow, ExUSSR Репутация: 4 Всего: 5 |
интересно, в свете проблемы с утечкой памяти при конкатенации (кстати, если я правильно тестил, то в 5.10 большинство проблем осталось), не происходит-ли утечки памяти при разименовывании ссылок?
например:
|
|||
|
||||
![]()
|
| Правила форума "Perl" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |