OVH Cloud OVH Cloud

libérer de la mémoire

9 réponses
Avatar
Scetbon Cyril
Salut,

j'ai un script qui utilise 20Mo de mémoire. Je me suis dis qu'en vidant
les tableaux et hashs que j'utilisais je descendrai en mémoire. (j'ai
aussi tenté un undef)
PAS DU TOUT
je me suis alors dit qu'il conservait cette mémoire au cas où, pour une
prochaine utilisation. Cependant, en créant une variable $pipo derrière
qui demande ~430ko derrière il n'utilise pas la mémoire qui devrait lui
être dispo mais prend à nouveau 430ko -> mon script utilise après 20mo
et 430 Ko.

Quelqu'un aurait il une explication ?
Peut on réellement libérer de la mémoire ? à quoi sert donc de vider des
tableaux qu'on utiliserait à part y retirer les éléments sans
conséquences pour la mémoire ?

PS: mes variables sont définies avec my, mais utilisé de façon globale.

Merci.

9 réponses

Avatar
Michel Rodriguez
Scetbon Cyril wrote:

Peut on réellement libérer de la mémoire ?


Non.

Perl ne rend pas la memoire qu'il utilise. Faire undef sur les variables
ne sert donc a rien. Par contre Perl re-utilise la memoire liberee.

--
Michel Rodriguez
Perl & XML
http://www.xmltwig.com

Avatar
Jérémy JUST
On Wed, 21 Apr 2004 12:39:35 +0200
Scetbon Cyril wrote:

j'ai un script qui utilise 20Mo de mémoire. Je me suis dis qu'en vidant
les tableaux et hashs que j'utilisais je descendrai en mémoire. (j'ai
aussi tenté un undef)


Oui, tu peux faire un
undef @tableau ;
pour te débarrasser de ton gros tableau.


PAS DU TOUT


Ne t'attends pas à ce que ton programme rende de la mémoire au système:
ce qui est pris par un processus l'est jusqu'à sa mort (sauf
réimplémentation particulière de malloc/free).
Ce comportement n'est pas lié à Perl.


je me suis alors dit qu'il conservait cette mémoire au cas où, pour une
prochaine utilisation.


Normalement, c'est le cas.


Cependant, en créant une variable $pipo derrière qui demande ~430ko
derrière il n'utilise pas la mémoire qui devrait lui être dispo mais
prend à nouveau 430ko


Tu devrais donner ton script (ou mieux: un script de quelques lignes qui
a un comportement équivalent), pour qu'on puisse regarder ça de plus près.


Peut on réellement libérer de la mémoire ?


On peut la libérer DANS un processus, pour la réutiliser dans le même
processus. Mais le système ne s'occupe pas de ça.
Si tu veux rendre de la mémoire au système, tu peux forker, tuer le père
et continuer avec le fils (en lui faisant emporter le strict minimum).
Pour 20 Mo, ça me semble compliqué (mais c'est comme ça que fonctionne
Apache, par exemple).


PS: mes variables sont définies avec my, mais utilisé de façon globale.


Une preuve que la mémoire est réutilisée:
$ perl -e 'while(1){$a = "AA"}'
prend une place constante en mémoire. Parce qu'à chaque itération, $a est
détruite et sa place est réutilisée.

--
Jérémy JUST

Avatar
DominiX
ici même:c65j3c$,
Scetbon Cyril a écrit
Salut,

j'ai un script qui utilise 20Mo de mémoire.
...


PS: mes variables sont définies avec my, mais utilisé de façon
globale.

c'est ça le problème, la vue globale...


si tu veux libérer de la mémoire il faut créer des process et les
tuer lorsque la job est terminé. (un peu lourd) ou (selon OS) utiliser
une compartimentation ( Safe::World )

Merci.


--
dominix

Avatar
Scetbon Cyril
DominiX wrote:
ici même:c65j3c$,
Scetbon Cyril a écrit

Salut,

j'ai un script qui utilise 20Mo de mémoire.


...

PS: mes variables sont définies avec my, mais utilisé de façon
globale.

cela n'a pas l'air d'être ça.



voici mon code test:

print "push";
push @a,'A'x1000 for(1..10000);
print "wait";
sleep 10;
print "splice";
splice @a,-4000;
print "wait;
sleep 10;
print "push";
{
push @a,'A'x1000 for(1..3000);
# push @b,'A'x1000 for(1..3000);
}
print "wait";
sleep 10;
__END__;

lorsque j'utilise le tableau @a la mémoire n'augmente pas, il la
réutilise bien.
Par contre, lorsque j'utilise le tableau @b qui n'a pas de porté globale
(!!!), il ne réutilise pas la mémoire du tableau @a mais redemande de la
mémoire. Je pense donc que le tableau @a a moins d'éléments mais occupe
autant de mémoire: OK.
Par contre le tableau @b, en dehors du bloc où il est utilisé n'a pas de
portée et donc devrait être détruit, d'où un gain en mémoire, non ?
pourtant, des tests me disent le contraire.

c'est ça le problème, la vue globale...

si tu veux libérer de la mémoire il faut créer des process et les
tuer lorsque la job est terminé. (un peu lourd) ou (selon OS) utiliser
une compartimentation ( Safe::World )


Merci.






Avatar
Paul GABORIT
À (at) Wed, 21 Apr 2004 19:56:03 +0200,
Michel Rodriguez écrivait (wrote):
Perl ne rend pas la memoire qu'il utilise. Faire undef sur les variables ne
sert donc a rien. Par contre Perl re-utilise la memoire liberee.


Pour être plus clair, si le tableau @A occupe 200Mo, lorsqu'on fait :

undef @A;

cela ne rend pas les 200Mo *au* *sytème* mais cela libère ces 200Mo pour un
autre usage dans perl. Donc appeler 'undef' ne sert qu'à perl. Pas au système.

Tout cela peut changer selon l'implémentation (c'est perl qui ne rend pas la
mémoire et non Perl).

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>

Avatar
Jérémy JUST
On Thu, 22 Apr 2004 14:27:21 +0200
Scetbon Cyril wrote:

voici mon code test:


Je ne vois pas bien où tu supprime ton tableau. Avec ton « splice » ? Je
doute que ça ait des chances de fonctionner...


Voici trois exemples de codes à partir du tien (les lignes qui changent
sont notées):

Le premier utilise 11 Mo de RAM pendant 20 secondes, puis monte jusqu'à
21 Mo (le tableau @a n'est pas supprimé).
<<<<<
print "push An" ;
push @a,'A'x1000 for(1..10000) ;
print "wait An" ;
sleep 20 ;

print "push Bn" ;
push @b,'A'x1000 for(1..10000) ;
print "wait Bn" ;
sleep 20 ;







Le deuxième utilise tout le temps 11 Mo de RAM (le tableau @a est
explicitement détruit; la mémoire est réutilisée pour @b).
<<<<<
print "push An" ;
push @a,'A'x1000 for(1..10000) ;
print "wait An" ;
sleep 20 ;

undef @a ; #####

print "push Bn" ;
push @b,'A'x1000 for(1..10000) ;
print "wait Bn" ;
sleep 20 ;







Le troisième utilise aussi tout le temps 11 Mo de RAM (le tableau @a est
détruit à la sortie du bloc; la mémoire est réutilisée pour @b).
<<<<<
{my @a ; #####
print "push An" ;
push @a,'A'x1000 for(1..10000) ;
print "wait An" ;
sleep 20 ;
} #####

print "push Bn" ;
push @b,'A'x1000 for(1..10000) ;
print "wait Bn" ;
sleep 20 ;







--
Jérémy JUST





Avatar
no
On Thu, 22 Apr 2004 14:27:21 +0200, Scetbon Cyril wrote:



DominiX wrote:
ici même:c65j3c$, Scetbon Cyril
a écrit

Salut,

j'ai un script qui utilise 20Mo de mémoire.


...

PS: mes variables sont définies avec my, mais utilisé de façon
globale.

cela n'a pas l'air d'être ça.



voici mon code test:

print "push";
push @a,'A'x1000 for(1..10000);
print "wait";
sleep 10;
print "splice";
splice @a,-4000;
print "wait;
sleep 10;
print "push";
{
push @a,'A'x1000 for(1..3000);
# push @b,'A'x1000 for(1..3000);
}
print "wait";
sleep 10;
__END__;

lorsque j'utilise le tableau @a la mémoire n'augmente pas, il la
réutilise bien.
Par contre, lorsque j'utilise le tableau @b qui n'a pas de porté
globale (!!!), il ne réutilise pas la mémoire du tableau @a mais
redemande de la mémoire. Je pense donc que le tableau @a a moins
d'éléments mais occupe autant de mémoire: OK.
Par contre le tableau @b, en dehors du bloc où il est utilisé n'a pas
de portée et donc devrait être détruit, d'où un gain en mémoire,
non ? pourtant, des tests me disent le contraire.


Quelle version de Perl ?

Parce qu'avec mon Perl-5.8 sur Linux (Fedora Core 1) il semble bien
reutiliser la mémoire liberé par le splice pour @b :

$ perl -e '
print "pushn";
push @a,"A"x1000 for(1..100000);

# ||
# <----- 100Mo ------>
#
# <------------------>
# perl = 100Mo

print "waitn";
sleep 10;
print "splicen";
splice @a,-50000;

# ||.........
# <---50Mo-->
#
# <------------------>
# perl = 100Mo

print "waitn";
sleep 10;
print "pushn";
{ push @b,"A"x1000 for(1..100000);}

# |||
# <---50Mo--><-------100Mo----->
#
# <---------------------------->
# perl = 150Mo

print "waitn";
sleep 10;'

Le splice ne redonne pas la mémoire au système, mais par contre perl la
reutilise pour @b, sinon j'aurais 200Mo pour le process perl et pas 150Mo.



Avatar
Jérémy JUST
On Thu, 22 Apr 2004 23:01:58 +0200
Jérémy JUST wrote:

Je ne vois pas bien où tu supprime ton tableau.
es!!


Avec ton « splice » ? Je doute que ça ait des chances de fonctionner...


Après lecture de la réponse de No, j'avoue avoir été médisant en ce qui
concerne l'intérêt du « splice ».

--
Jérémy JUST

Avatar
Scetbon Cyril
no wrote:
On Thu, 22 Apr 2004 14:27:21 +0200, Scetbon Cyril wrote:



DominiX wrote:

ici même:c65j3c$, Scetbon Cyril
a écrit


Salut,

j'ai un script qui utilise 20Mo de mémoire.


...


PS: mes variables sont définies avec my, mais utilisé de façon
globale.




cela n'a pas l'air d'être ça.

voici mon code test:

print "push";
push @a,'A'x1000 for(1..10000);
print "wait";
sleep 10;
print "splice";
splice @a,-4000;
print "wait;
sleep 10;
print "push";
{
push @a,'A'x1000 for(1..3000);
# push @b,'A'x1000 for(1..3000);
}
print "wait";
sleep 10;
__END__;

lorsque j'utilise le tableau @a la mémoire n'augmente pas, il la
réutilise bien.
Par contre, lorsque j'utilise le tableau @b qui n'a pas de porté
globale (!!!), il ne réutilise pas la mémoire du tableau @a mais
redemande de la mémoire. Je pense donc que le tableau @a a moins
d'éléments mais occupe autant de mémoire: OK.
Par contre le tableau @b, en dehors du bloc où il est utilisé n'a pas
de portée et donc devrait être détruit, d'où un gain en mémoire,
non ? pourtant, des tests me disent le contraire.



Quelle version de Perl ?

Parce qu'avec mon Perl-5.8 sur Linux (Fedora Core 1)
la même mais sous Win2000 pro

j'ai pas testé sur ma machine linux...
Remarque, c'est plutôt interne à Perl le fait de réutiliser de la
mémoire dispo ou pas qd même, donc ça devrait pas varier entre les 2.
mais je vais tester qd même.
il semble bien
reutiliser la mémoire liberé par le splice pour @b :

$ perl -e '
print "pushn";
push @a,"A"x1000 for(1..100000);

# ||
# <----- 100Mo ------>
#
# <------------------>
# perl = 100Mo

print "waitn";
sleep 10;
print "splicen";
splice @a,-50000;

# ||.........
# <---50Mo-->
#
# <------------------>
# perl = 100Mo

print "waitn";
sleep 10;
print "pushn";
{ push @b,"A"x1000 for(1..100000);}

# |||
# <---50Mo--><-------100Mo----->
#
# <---------------------------->
# perl = 150Mo

print "waitn";
sleep 10;'

Le splice ne redonne pas la mémoire au système, mais par contre perl la
reutilise pour @b, sinon j'aurais 200Mo pour le process perl et pas 150Mo.