This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix mallinfo() to accumulate results for all arenas.


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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]