improve memory allocation statistics report

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@38773 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2015-07-09 11:37:37 +00:00
parent 8f2ccfe42e
commit 73c1258d5a
2 changed files with 140 additions and 128 deletions

View file

@ -1,3 +1,8 @@
2015-07-09 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSDebug.m: List memory allocation statistics in alphabetical
order (by class name) for easier interpretation.
2015-07-08 Richard Frith-Macdonald <rfm@gnu.org> 2015-07-08 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSLock.h: * Headers/Foundation/NSLock.h:

View file

@ -40,6 +40,8 @@
#import "Foundation/NSThread.h" #import "Foundation/NSThread.h"
#import "Foundation/NSValue.h" #import "Foundation/NSValue.h"
#import "GSSorting.h"
#if HAVE_EXECINFO_H #if HAVE_EXECINFO_H
#include <execinfo.h> #include <execinfo.h>
#endif #endif
@ -59,6 +61,16 @@ typedef struct {
unsigned int stack_size; unsigned int stack_size;
} table_entry; } table_entry;
typedef struct {
const char *name;
int count;
} list_entry;
static NSInteger itemComp(id v0, id v1, void *ctxt)
{
return strcmp(((list_entry*)v0)->name, ((list_entry *)v1)->name);
}
static unsigned int num_classes = 0; static unsigned int num_classes = 0;
static unsigned int table_size = 0; static unsigned int table_size = 0;
@ -72,8 +84,8 @@ static SEL unLockSel = 0;
static IMP doLockImp = 0; static IMP doLockImp = 0;
static IMP unLockImp = 0; static IMP unLockImp = 0;
static const char* _GSDebugAllocationList(BOOL difference); static void _GSDebugAllocationFetch(list_entry *items, BOOL difference);
static const char* _GSDebugAllocationListAll(void); static void _GSDebugAllocationFetchAll(list_entry *items);
static void _GSDebugAllocationAdd(Class c, id o); static void _GSDebugAllocationAdd(Class c, id o);
static void _GSDebugAllocationRemove(Class c, id o); static void _GSDebugAllocationRemove(Class c, id o);
@ -402,76 +414,131 @@ GSDebugAllocationClassList()
const char* const char*
GSDebugAllocationList(BOOL changeFlag) GSDebugAllocationList(BOOL changeFlag)
{ {
const char *ans; list_entry *items;
NSData *d; unsigned size;
if (debug_allocation == NO) if (debug_allocation == NO)
{ {
return "Debug allocation system is not active!\n"; return "Debug allocation system is not active!\n";
} }
doLock(); doLock();
ans = _GSDebugAllocationList(changeFlag); size = num_classes;
d = [NSData dataWithBytes: ans length: strlen(ans) + 1]; if (size > 0)
{
items = malloc(sizeof(list_entry) * size);
_GSDebugAllocationFetch(items, changeFlag);
}
else
{
items = 0;
}
unLock(); unLock();
return (const char*)[d bytes];
while (size > 0 && 0 == items[size - 1].name)
{
size--;
}
if (0 == size)
{
if (items != 0)
{
free(items);
}
if (changeFlag)
{
return "There are NO newly allocated or deallocated object!\n";
}
else
{
return "I can find NO allocated object!\n";
}
}
else
{
NSMutableString *result;
id order[size];
unsigned index;
for (index = 0; index < size; index++)
{
order[index] = (id)&items[index];
}
GSSortUnstable(order, NSMakeRange(0,size), (id)itemComp,
GSComparisonTypeFunction, 0);
result = [NSMutableString stringWithCapacity: 1000];
for (index = 0; index < size; index++)
{
list_entry *item = (list_entry*)order[index];
[result appendFormat: @"%d\t%s\n", item->count, item->name];
}
free(items);
return [result UTF8String];
}
} }
static const char* const char*
_GSDebugAllocationList(BOOL difference) GSDebugAllocationListAll()
{ {
unsigned int pos = 0; list_entry *items;
unsigned int i; unsigned size;
static unsigned int siz = 0;
static char *buf = 0;
for (i = 0; i < num_classes; i++) if (debug_allocation == NO)
{ {
int val = the_table[i].count; return "Debug allocation system is not active!\n";
if (difference)
{
val -= the_table[i].lastc;
}
if (val != 0)
{
pos += 22 + strlen(class_getName(the_table[i].class));
}
}
if (pos == 0)
{
if (difference)
{
return "There are NO newly allocated or deallocated object!\n";
}
else
{
return "I can find NO allocated object!\n";
}
} }
pos++; doLock();
size = num_classes;
if (pos > siz) if (size > 0)
{ {
if (pos & 0xff) items = malloc(sizeof(list_entry) * size);
{ _GSDebugAllocationFetchAll(items);
pos = ((pos >> 8) + 1) << 8;
}
siz = pos;
if (buf)
{
NSZoneFree(NSDefaultMallocZone(), buf);
}
buf = NSZoneMalloc(NSDefaultMallocZone(), siz);
} }
else
if (0 == buf)
{ {
return ""; items = 0;
} }
unLock();
pos = 0; if (0 == items)
for (i = 0; i < num_classes; i++) {
return "I can find NO allocated object!\n";
}
else
{
NSMutableString *result;
id order[size];
unsigned index;
for (index = 0; index < size; index++)
{
order[index] = (id)&items[index];
}
GSSortUnstable(order, NSMakeRange(0,size), (id)itemComp,
GSComparisonTypeFunction, 0);
result = [NSMutableString stringWithCapacity: 1000];
for (index = 0; index < size; index++)
{
list_entry *item = (list_entry*)order[index];
[result appendFormat: @"%d\t%s\n", item->count, item->name];
}
free(items);
return [result UTF8String];
}
}
static void
_GSDebugAllocationFetch(list_entry *items, BOOL difference)
{
unsigned i;
unsigned pos;
for (i = pos = 0; i < num_classes; i++)
{ {
int val = the_table[i].count; int val = the_table[i].count;
@ -480,91 +547,31 @@ _GSDebugAllocationList(BOOL difference)
val -= the_table[i].lastc; val -= the_table[i].lastc;
} }
the_table[i].lastc = the_table[i].count; the_table[i].lastc = the_table[i].count;
if (val)
if (val != 0) {
{ items[pos].name = class_getName(the_table[i].class);
snprintf(&buf[pos], siz - pos, "%d\t%s\n", items[pos].count = val;
val, class_getName(the_table[i].class)); pos++;
pos += strlen(&buf[pos]); }
}
} }
while (pos < num_classes)
return buf;
}
const char*
GSDebugAllocationListAll()
{
const char *ans;
NSData *d;
if (debug_allocation == NO)
{ {
return "Debug allocation system is not active!\n"; items[pos].name = 0;
items[pos].count = 0;
pos++;
} }
doLock();
ans = _GSDebugAllocationListAll();
d = [NSData dataWithBytes: ans length: strlen(ans)+1];
unLock();
return (const char*)[d bytes];
} }
static const char* static void
_GSDebugAllocationListAll(void) _GSDebugAllocationFetchAll(list_entry *items)
{ {
unsigned int pos = 0; unsigned i;
unsigned int i;
static unsigned int siz = 0;
static char *buf = 0;
for (i = 0; i < num_classes; i++) for (i = 0; i < num_classes; i++)
{ {
int val = the_table[i].total; items[i].name = class_getName(the_table[i].class);
items[i].count = the_table[i].total;
if (val != 0)
{
pos += 22 + strlen(class_getName(the_table[i].class));
}
} }
if (pos == 0)
{
return "I can find NO allocated object!\n";
}
pos++;
if (pos > siz)
{
if (pos & 0xff)
{
pos = ((pos >> 8) + 1) << 8;
}
siz = pos;
if (buf)
{
NSZoneFree(NSDefaultMallocZone(), buf);
}
buf = NSZoneMalloc(NSDefaultMallocZone(), siz);
}
if (0 == buf)
{
return "";
}
pos = 0;
for (i = 0; i < num_classes; i++)
{
int val = the_table[i].total;
if (val != 0)
{
snprintf(&buf[pos], siz - pos, "%d\t%s\n",
val, class_getName(the_table[i].class));
pos += strlen(&buf[pos]);
}
}
return buf;
} }
void void