[Vienna-pm] Garbage-Collection

Leopold Toetsch lt at toetsch.at
Thu Aug 11 06:04:29 PDT 2005


Peter J. Holzer wrote:

> Ja, das ist das traditionelle Verhalten von Unix-malloc. Die glibc hat
> allerdings ein anderes Verhalten: Große Memory-Blöcke (über 128 kB,
> IIRC) werden sofort ans OS zurückgegeben, kleine werden "recycelt" und
> nur zurückgegeben, wenn es sich auszahlt. 

Yep. Siehe auch $glibc_src/malloc.c:

#define DEFAULT_MMAP_THRESHOLD (128 * 1024)

D.h. perl kann zwar Speicher freigeben, aber es hängt von der libc ab, 
ob der Speicher tatsächlich für andere Anwendungen frei verfügbar wird.
Bei kleinen Blöcken ist das nie der Fall, bei großen *kann* der Speicher 
verfügbar werden, wenn die Fragmentierung das zuläßt.

> Noch eine kleine Beobachtung:

> Wenn man die Schleife aber entrollt:

>     $s = "A" x 10_000_000;

>     # B
>     $s = "B" x 10_000_000;

> Dann steigt der Speicherverbrauch mit jeder Zuweisung eines "großen"
> Strings um 10 MB an.

Das ist nicht so verwunderlich. In Parrot würde das so ausschauen:

   $S0 = repeat "A", 10000000
   $P0 = new .String
   $P0 = $S0
   store_lex -1, "$s", $P0
   $P0 = "x"

   $S1 = repeat "B", 10000000
   $P1 = new .String
   $P1 = $S1
   store_lex -1, "$s", $P1
   $P1 = "x"

Nun kommt es darauf an, ob der Registerallocator die temporären Strings 
($S0, $S1) oder ($P0, $P1) an separate Register zuweist, oder ob die 
Register wiederverwendet werden. Nur in letzterem Fall würde der 
Speicherverbrauch nicht ansteigen (tatsächlich werden die Register 
wiederverwendet, wenn sie später nicht mehr referenziert sind).

In Perl schaut das aber anders aus. Die Ausgabe von:

$ perl -MO=Concise,-exec hjp.pl
...
   repeat[t2] ..
   ...
   repeat[t7] ...

scheint anzudeuten, daß die temporären Strings verschieden sind. Nun 
sollte man annehmen, daß der Refcount des temporären Strings am Stack 
nach "Verbrauch" des Temps 0 werden sollte. Aber hier schlägt eine 
"Optimierung" von perl zu: Die SVs am Stack werden nicht refgecounted, 
d.h. ein SvREFCNT_dec() findet erst  in Perl_leave_scope() statt.

Allerdings

   do {
        blabla;
   };

oder oder if (1) {} hilft auch nicht. D.h. temporäre Speicherfresser 
sollten in eigene Unterprogramme ausgelagert werden.

> 	hp

leo



More information about the Vienna-pm mailing list