[patch] Fix mallinfo() to accumulate results for all arenas.
Paul Pluzhnikov
ppluzhnikov@google.com
Tue Aug 23 22:43:00 GMT 2011
Greetings,
We've noticed that mallinfo() gives wildly inaccurate results, and it
appears that it was never updated for multiple arenas.
Here is a test case:
/// --- cut ----
#include <malloc.h>
#include <stdio.h>
#include <pthread.h>
unsigned long total;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
const size_t _1M = (1 << 20);
const size_t _1G = (1 << 30);
void *fn (void *p)
{
int i;
size_t size;
size = 128;
for (i = 0; i < 500; i++)
{
p = malloc (size);
if (p != NULL)
{
pthread_mutex_lock(&mtx);
total += size;
pthread_mutex_unlock(&mtx);
size *= 1.01;
}
else
break;
}
return NULL;
}
#define NTHR 10
int main()
{
int i, size;
struct mallinfo info;
pthread_t tid[NTHR];
void *p;
for (i = 0; i < NTHR; i++) {
pthread_create(&tid[i], NULL, fn, NULL);
}
for (i = 0; i < NTHR; i++) {
pthread_join(tid[i], NULL);
}
size = 128;
for (i = 0; i < 500; ++i) {
p = malloc(size);
if (p != NULL)
{
total += size;
size *= 1.01;
}
else
break;
}
printf("My total:\t\t%lu\n", total);
info = mallinfo();
printf("Via mallinfo (used):\t%lu\n", (unsigned long) info.uordblks);
printf(" (capacity):\t%lu\n", (unsigned long) info.arena + info.hblkhd);
malloc_stats();
return 0;
}
/// --- cut ----
The output:
gcc -g -m32 -pthread t.c && ./a.out
My total: 12129414
Via mallinfo (used): 1360712
(capacity): 1363968
Arena 0:
system bytes = 1363968
in use bytes = 1360712
Arena 1:
system bytes = 1191936
in use bytes = 1098608
...
Arena 9:
system bytes = 1191936
in use bytes = 1108792
Total (incl. mmap):
system bytes = 12746752
in use bytes = 12181224
max mmap regions = 0
max mmap bytes = 0
Attached patch fixes mallinfo() to accumulate over all arenas, and makes
the mallinfo() result much more useful:
My total: 12129414
Via mallinfo (used): 12182408
(capacity): 13107200
Arena 0:
system bytes = 1228800
in use bytes = 1106968
Arena 1:
system bytes = 1187840
in use bytes = 1107544
...
Arena 10:
system bytes = 1187840
in use bytes = 1107544
Total (incl. mmap):
system bytes = 13107200
in use bytes = 12182408
max mmap regions = 0
max mmap bytes = 0
Thanks,
--
Paul Pluzhnikov
2011-08-23 Paul Pluzhnikov <ppluzhnikov@google.com>
* malloc/malloc.c (mALLINFo): Adjust prototype.
(public_mALLINFo): Iterate over all arenas.
(mALLINFo, mSTATs): Adjust.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index dccb6cc..8d32bee 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1632,7 +1632,7 @@ static int mTRIm(mstate, size_t);
static size_t mUSABLe(Void_t*);
static void mSTATs(void);
static int mALLOPt(int, int);
-static struct mallinfo mALLINFo(mstate);
+static void mALLINFo(mstate, struct mallinfo *m);
static void malloc_printerr(int action, const char *str, void *ptr);
static Void_t* internal_function mem2mem_check(Void_t *p, size_t sz);
@@ -1681,7 +1681,7 @@ static int mTRIm();
static size_t mUSABLe();
static void mSTATs();
static int mALLOPt();
-static struct mallinfo mALLINFo();
+static void mALLINFo();
#endif
@@ -4223,12 +4223,22 @@ public_mSTATs()
struct mallinfo public_mALLINFo()
{
struct mallinfo m;
+ mstate ar_ptr;
+
+ memset(&m, 0, sizeof(m));
if(__malloc_initialized < 0)
ptmalloc_init ();
- (void)mutex_lock(&main_arena.mutex);
- m = mALLINFo(&main_arena);
- (void)mutex_unlock(&main_arena.mutex);
+
+ for (ar_ptr = &main_arena;;)
+ {
+ (void)mutex_lock(&ar_ptr->mutex);
+ mALLINFo(ar_ptr, &m);
+ (void)mutex_unlock(&ar_ptr->mutex);
+
+ ar_ptr = ar_ptr->next;
+ if(ar_ptr == &main_arena) break;
+ }
return m;
}
@@ -5912,9 +5922,8 @@ size_t mUSABLe(mem) Void_t* mem;
------------------------------ mallinfo ------------------------------
*/
-struct mallinfo mALLINFo(mstate av)
+void mALLINFo(mstate av, struct mallinfo *m)
{
- struct mallinfo mi;
size_t i;
mbinptr b;
mchunkptr p;
@@ -5954,17 +5963,19 @@ struct mallinfo mALLINFo(mstate av)
}
}
- mi.smblks = nfastblocks;
- mi.ordblks = nblocks;
- mi.fordblks = avail;
- mi.uordblks = av->system_mem - avail;
- mi.arena = av->system_mem;
- mi.hblks = mp_.n_mmaps;
- mi.hblkhd = mp_.mmapped_mem;
- mi.fsmblks = fastavail;
- mi.keepcost = chunksize(av->top);
- mi.usmblks = mp_.max_total_mem;
- return mi;
+ m->smblks += nfastblocks;
+ m->ordblks += nblocks;
+ m->fordblks += avail;
+ m->uordblks += av->system_mem - avail;
+ m->arena += av->system_mem;
+ m->fsmblks += fastavail;
+ if (av == &main_arena)
+ {
+ m->hblks = mp_.n_mmaps;
+ m->hblkhd = mp_.mmapped_mem;
+ m->usmblks = mp_.max_total_mem;
+ m->keepcost = chunksize(av->top);
+ }
}
/*
@@ -5989,8 +6000,9 @@ void mSTATs()
((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
#endif
for (i=0, ar_ptr = &main_arena;; i++) {
+ memset(&mi, 0, sizeof(mi));
(void)mutex_lock(&ar_ptr->mutex);
- mi = mALLINFo(ar_ptr);
+ mALLINFo(ar_ptr, &mi);
fprintf(stderr, "Arena %d:\n", i);
fprintf(stderr, "system bytes = %10u\n", (unsigned int)mi.arena);
fprintf(stderr, "in use bytes = %10u\n", (unsigned int)mi.uordblks);
More information about the Libc-alpha
mailing list