Julian Seward 080c67f88d Avoid excessive fragmentation in m_mallocfree facility by munmapping
unused superblocks in some circumstances.  Bug 250101 (==269884,
==275852)
(Philippe Waroquiers, philippe.waroquiers@skynet.be)



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@11911
2011-07-24 17:39:10 +00:00

94 lines
3.0 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#define BIGINCREASE 32000
int debug = 0;
void stats(char *msg)
{
struct mallinfo mallinfo_result;
mallinfo_result = mallinfo();
/* from /usr/include/malloc.h */
printf("%s\n", msg);
printf("%10d int arena; /* non-mmapped space allocated from system */\n", mallinfo_result.arena);
printf("%10d int ordblks; /* number of free chunks */\n", mallinfo_result.ordblks);
printf("%10d int smblks; /* number of fastbin blocks */\n", mallinfo_result.smblks);
printf("%10d int hblks; /* number of mmapped regions */\n", mallinfo_result.hblks);
printf("%10d int hblkhd; /* space in mmapped regions */\n", mallinfo_result.hblkhd);
printf("%10d int usmblks; /* maximum total allocated space */\n", mallinfo_result.usmblks);
printf("%10d int fsmblks; /* space available in freed fastbin blocks */\n", mallinfo_result.fsmblks);
printf("%10d int uordblks; /* total allocated space */\n", mallinfo_result.uordblks);
printf("%10d int fordblks; /* total free space */\n", mallinfo_result.fordblks);
printf("%10d int keepcost; /* top-most, releasable (via malloc_trim) space */\n", mallinfo_result.keepcost);
printf("\n");
}
int main(int argc, char *argv[])
{
char *big = NULL;
char *newbig;
int malloc_failure = 0;
unsigned long bigsize = 8; // current size of the (reallocated) big block.
int i;
int loop;
// two optional arguments: [nr of loop] [debug]
if (argc > 1)
loop = atoi(argv[1]);
else
loop = 3000;
if (argc > 2)
debug = 1;
bigsize += BIGINCREASE;
big = malloc (bigsize);
if (big == NULL)
printf ("failure %d could not allocate size %lu\n",
++malloc_failure, bigsize);
if (debug)
printf("big 0x%p\n", big);
for (i = 0; i < loop; i++)
{
bigsize += BIGINCREASE;
newbig = malloc(bigsize);
if (newbig == NULL)
printf ("failure %d could not allocate size %lu\n",
++malloc_failure, bigsize);
free (big);
big = newbig;
if (debug)
printf("big 0x%p\n", big);
}
printf ("after %d loops, last size block requested %lu\n", loop, bigsize);
// verify if superblock fragmentation occured
// We consider that an arena of up to 3 times more than bigsize is ok.
{
struct mallinfo mallinfo_result;
mallinfo_result = mallinfo();
// Under valgrind, hblkhd is 0 : all the space is in arena.
// Under native linux, some space is counted hblkhd.
if (malloc_failure > 0)
printf ("%d mallocs failed, below output is doubful\n", malloc_failure);
if (mallinfo_result.arena + mallinfo_result.hblkhd > 3 * bigsize)
printf("unexpected heap fragmentation %lu\n",
(unsigned long) mallinfo_result.arena
+ (unsigned long) mallinfo_result.hblkhd);
else
printf("reasonable heap usage\n");
}
if (debug)
stats ("before freeing last block");
free (big);
if (debug)
stats ("after freeing last block");
return 0;
}