Heap management

Giorgos Keramidas keramida at ceid.upatras.gr
Fri Oct 27 16:02:22 EEST 2006


On 2006-10-27 14:17, V13 <v13 at priest.com> wrote:
> On Friday 27 October 2006 11:00, Christos Ricudis wrote:
> > Standard malloc() behaviour. H malloc (den kserw ti ginetai sthn C++,
> > alla ypo8etw oti h new sthn ousia th malloc() kalei)
> > mporei na desmeysei mnhmh, alla h free() den einai pote ypoxrewmenh na
> > thn epistrepsei sto leitourgiko systhma, kai prepei na ypo8eseis oti DEN
> > to kanei.
> 
> Apo th glibc 2.3 kai meta h malloc() epistrefei mnimi me mmap() sto
> /dev/zero. Ayto exei san apotelesma h mnhmh ayti na ginetai pragmatika
> free otan einai pia eleytheri. (To documentation leei oti ayto ginetai
> sigoyra mono gia megala blocks, alla ap'oti exo dei to kanei kai gia
> mikra.  Isos to kanei emesa zitontas mnimi gia ton eayto ths meso ths
> mmap())
> 
> To programa poy yparxei sto telos se emena ftanei na troei peripoy
> 13MB mnimi kai molis ginei free() h malloc()ed mnimi peytei sta 3MB
> peripoy.

> ------------------
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> 
> #define SZ      100000
> #define BLKSZ   100
> 
> int main()
> {
>         int     n;
>         char    *ptr[SZ];
> 
>         fprintf(stderr, "Started...\n");
>         for (n=0; n<SZ; n++)
>         {
>                 ptr[n]=(char *)malloc(BLKSZ);
>                 *((ptr[n])+50)='a';
>         }
> 
>         fprintf(stderr, "Malloced...\n");
>         sleep(5);
> 
>         fprintf(stderr, "Freeing...\n");
>         for (n=0; n<SZ; n++)
>                 free(ptr[n]);
>         fprintf(stderr, "Freeed...\n");
> 
>         sleep(5);
>         fprintf(stderr, "The end...\n");
> }
> ------------------

Συγγνώμη, αλλά δε λέει τίποτα αυτό.  Για να είσαι σίγουρος ότι όντως
αυτό συμβαίνει πρέπει να δοκιμάσεις με κάτι σαν:

    #define BLKMINSIZE  32
    #define BLKSTEPSIZE	32
    #define BLKMAXSIZE	((size_t)4 * 1024 * 1024)

    #define NALLOCMIN   32
    #define NALLOCSTEP  32
    #define NALLOCMAX   ((size_t)8192)

    for (bsize = BLKMINSIZE; bsize <= BLKMAXSIZE; bsize += BLKSTEPSIZE) {
        for (nblks = NALLOCMIN; nblks <= NALLOCMAX; nblks += NALLOCSTEP) {
            runtest(bsize, nblks);
        }
    }

Όπου η runtest() τρέχει ένα ξεχωριστό process, και κάνει κάτι σαν:

    [1] Βρίσκει το αρχικό virtual size (α)
    [2] Κάνει malloc() `nblks' blocks των `bsize' bytes
    [3] Βρίσκει το νέο virtual size (β)
    [4] Κάνει free() όλα τα blocks
    [5] Βρίσκει το τελικό virtual size (γ)
    [6] Επιστρέφει (ή τυπώνει) τα:
        (bsize, nblks, α, β, γ)

Μπορεί για το συγκεκριμένο σετ από defines που διάλεξες και στον
συγκεκριμένο allocator που χρησιμοποιήσες, να είναι όντως έτσι.  Μπορεί
όμως, αν αρχίσεις να ζωγραφίζεις σε ένα 3-D διάγραμμα τα δεδομένα του
test που περιγράφω παραπάνω, απεικονίζοντας στο ίδιο γράφημα:

    * Το (α) ως συνάρτηση των (bsize, nblks)
    * Το (β) ως συνάρτηση των (bsize, nblks)
    * Το (γ) ως συνάρτηση των (bsize, nblks)

Αν δεις πως υπάρχουν 'περίεργα' spikes και ανωμαλίες στα σημεία που ο
συγκεκριμένος allocator αλλάζει allocation 'πολιτική', αλλάξει arena
size, παίρνει μνήμη από το λειτουργικό αλλά δεν την επιστρέφει αμέσως,
κλπ. τότε μπορεί να μην είναι τόσο προφανές απλά κοιτάζοντας το μέγιστο
virtual size του προγράμματος γιατί γίνεται το κάθε ένα από αυτά που
βλέπεις.

Επίσης, κάτι που είναι σημαντικό και *δεν* φαίνεται σε αυτό το test
είναι τι γίνεται με πιο 'πραγματικά' use patterns και τον ίδιο
allocator.

Αν το κάνεις όλο αυτό, τότε θέλω να δω το paper που θα βγει ως
αποτέλεσμα, και θέλω να δω και το source από τα tests, για να τρέξω με
2-3 διαφορετικές malloc implementations :-)




More information about the Linux-greek-users mailing list