mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-03 01:50:55 +00:00
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:
parent
8f2ccfe42e
commit
73c1258d5a
2 changed files with 140 additions and 128 deletions
|
@ -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:
|
||||||
|
|
263
Source/NSDebug.m
263
Source/NSDebug.m
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue