LINUX.ORG.RU

Perl и память


0

0

Вопрос 1:

Вот простенький скрипт:

#!/usr/bin/perl -w

foreach $i (0..1000000){
push(@t,$i);
}

print "$#t\n";
sleep 3;

$#t=-1;

print "$#t\n";

sleep 3;

Во время его работы смотрим в top и видим что после выполнения $#t=-1; память не очистилась. Почему?

Вопрос 2:

Вот еще один пример:

#!/usr/bin/perl -w

open(FIL,"test.bin");

while(<FIL>){
s{(.)(?{push(@t,$1)})}{}g;
}

close FIL;

print "$#t\n";
sleep 3;

$#t=-1;

print "$#t\n";

sleep 3;


Пусть test.bin - бинарный файл имеет размер 1 000 000 байт, для совпадения с размером массива из предыдущего примера. Во время его выполнения опять же смотрим в top и видим что занимаемая память больше, чем в примере 1. Почему?

Вопрос 3:

Если в примере 2 заменить

s{(.)(?{push(@t,$1)})}{}g;

на

s{(.)(?{push(@t,ord($1))})}{}g;

то памяти откушается еще больше. Почему?

Тем кто не знает что такое ord(), а искать влом:

Definition ord():

This function returns the numeric ASCII code of the first character in the expression (or $_ if none specified).

Example
print("ord() ",ord("A"), "\n");


Всем принявшим участие в обсуждении заранее благодарен.

anonymous

первый вопрос не про перл а про malloc.
представьте, что вы на С делаете:

void* set[COUNT];

for (i = 0; i < COUNT; ++i)
        set[i] = malloc(16);
// занято ~ 16 * COUNT

for (i = 0; i < COUNT - 1; ++i)
        free(set[i]);
// а занято по-прежнему 16 * COUNT хотя мы почти все
// "освободили"

free(set[COUNT-1]);
// а вот теперь 16 * COUNT действительно освободили

причина в том, что мы делаем много маленьких allocations,
brk растет, но мы не можем вернуть память ядру из середины
heap, a вот когда мы освободили последний элемент, libc
может вернуть brk назад.

idle ★★★★★
()
Ответ на: комментарий от anonymous

> Ну даже если вместо

да какая разница? ну прочитайте еще раз, что я
написал, понятнее все равно не смогу обьяснить.
повторю, дело не в perl, дело в malloc().

idle ★★★★★
()
Ответ на: комментарий от idle

У перла свои механизмы работы с памятью. "Освобожденную" память он как правило (если не всегда) не отпускает, а держит. При этом она может быть отдана под другие используемые переменные. Но может и не быть отдана %))

ach
()
Ответ на: комментарий от idle

поймите, perl тоже вызывает malloc() для
своих нужд постоянно, и наверняка что-то
аллокировал послетого, как вы добавили
последний элемент в массив.

кстати. после @array = () будут освобождены
только элементы массива, память для самого
массива освобождена не будет, это уже политика
perl.

~$ perl -MDevel::Peek -e '@_=(1..1000); @_=(); Dump \@_'
SV = RV(0x80fb734) at 0x811520c
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x80ef784
  SV = PVAV(0x80f0ba8) at 0x80ef784
    REFCNT = 2
    FLAGS = ()
    IV = 0
    NV = 0
    ARRAY = 0x810e9a0
    FILL = -1
    MAX = 999     <-----------------
    ARYLEN = 0x0
    FLAGS = (REAL)

idle ★★★★★
()
Ответ на: комментарий от ach

> У перла свои механизмы работы с памятью. 

да, есть usemymalloc, но здесь не при чем

> он как правило (если не всегда) не отпускает, а держит.

только надо прояснить, что значит держит. если это
означает, что не возвращает память ядру (brk,unmap),
и если "как правило" заменить на "не всегда" то так
работает любой алгоритм распределения памяти.
но сам perl память _освобождает_.

вот пример.
~$ perl -e 'sub M{system"grep VmData /proc/$$/status"} push @_,"x"x1000000 for 1..32; M; @_=(); M'
VmData:    32560 kB
VmData:     1200 kB

видно, что память освобождается. потому, что для больших
allocations malloc() использует mmap(), и free() может
вернуть память ядру.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.