|
|
|
@ -11,11 +11,6 @@
|
|
|
|
|
#define PROFILER_HASHTABLE_SIZE 1024 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static profiler_mem stats_mem = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
|
|
|
|
static GStaticMutex profiler_mutex = G_STATIC_MUTEX_INIT; |
|
|
|
|
static gboolean profiler_enabled = FALSE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct profiler_entry { |
|
|
|
|
gpointer addr; |
|
|
|
|
gsize len; |
|
|
|
@ -23,6 +18,12 @@ struct profiler_entry {
|
|
|
|
|
}; |
|
|
|
|
typedef struct profiler_entry profiler_entry; |
|
|
|
|
|
|
|
|
|
static profiler_mem stats_mem = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
|
|
|
|
static GStaticMutex profiler_mutex = G_STATIC_MUTEX_INIT; |
|
|
|
|
static gboolean profiler_enabled = FALSE; |
|
|
|
|
static profiler_entry *free_list = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct { |
|
|
|
|
profiler_entry **nodes; |
|
|
|
|
} profiler_hashtable; |
|
|
|
@ -31,8 +32,15 @@ static void profiler_hashtable_init() {
|
|
|
|
|
profiler_hashtable.nodes = calloc(1, sizeof(profiler_entry*) * PROFILER_HASHTABLE_SIZE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static guint profiler_hash_addr(gpointer addr) { |
|
|
|
|
guint h = (gsize) addr; |
|
|
|
|
h = (h >> 3) * 2654435761; /* ~ golden ratio of 2^32, shift 3 because of 8 byte boundary alignment (use 2 for 4 byte boundary) */ |
|
|
|
|
//printf("hashing addr 0x%zx: %u ([%u])\n", (gsize)addr, h, h % PROFILER_HASHTABLE_SIZE);
|
|
|
|
|
return h % PROFILER_HASHTABLE_SIZE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static profiler_entry *profiler_hashtable_find(gpointer addr) { |
|
|
|
|
guint h = (gsize)addr % PROFILER_HASHTABLE_SIZE; |
|
|
|
|
guint h = profiler_hash_addr(addr); |
|
|
|
|
|
|
|
|
|
for (profiler_entry *e = profiler_hashtable.nodes[h]; e != NULL; e = e->next) { |
|
|
|
|
if (e->addr == addr) |
|
|
|
@ -43,13 +51,14 @@ static profiler_entry *profiler_hashtable_find(gpointer addr) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void profiler_hashtable_insert(gpointer addr, gsize len) { |
|
|
|
|
profiler_entry *e = malloc(sizeof(profiler_entry)); |
|
|
|
|
profiler_entry *e = free_list; |
|
|
|
|
free_list = free_list->next ? free_list->next : calloc(1, sizeof(profiler_entry)); |
|
|
|
|
|
|
|
|
|
e->addr = addr; |
|
|
|
|
e->len = len; |
|
|
|
|
e->next = NULL; |
|
|
|
|
|
|
|
|
|
guint h = (gsize)addr % PROFILER_HASHTABLE_SIZE; |
|
|
|
|
guint h = profiler_hash_addr(addr); |
|
|
|
|
|
|
|
|
|
if (profiler_hashtable.nodes[h] == NULL) { |
|
|
|
|
profiler_hashtable.nodes[h] = e; |
|
|
|
@ -65,7 +74,7 @@ static void profiler_hashtable_insert(gpointer addr, gsize len) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void profiler_hashtable_remove(gpointer addr) { |
|
|
|
|
guint h = (gsize)addr % PROFILER_HASHTABLE_SIZE; |
|
|
|
|
guint h = profiler_hash_addr(addr); |
|
|
|
|
profiler_entry *prev = profiler_hashtable.nodes[h]; |
|
|
|
|
|
|
|
|
|
if (!prev) |
|
|
|
@ -83,7 +92,8 @@ static void profiler_hashtable_remove(gpointer addr) {
|
|
|
|
|
for (profiler_entry *e = prev->next; e != NULL; e = e->next) { |
|
|
|
|
if (e->addr == addr) { |
|
|
|
|
prev->next = e->next; |
|
|
|
|
free(e); |
|
|
|
|
e->next = free_list; |
|
|
|
|
free_list = e; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
prev = e; |
|
|
|
@ -202,6 +212,13 @@ void profiler_enable() {
|
|
|
|
|
profiler_enabled = TRUE; |
|
|
|
|
|
|
|
|
|
profiler_hashtable_init(); |
|
|
|
|
/* prealloc 50 hashtable entries */ |
|
|
|
|
free_list = calloc(1, sizeof(profiler_entry)); |
|
|
|
|
for (guint i = 0; i < 49; i++) { |
|
|
|
|
profiler_entry *e = calloc(1, sizeof(profiler_entry)); |
|
|
|
|
e->next = free_list; |
|
|
|
|
free_list = e; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
t.malloc = profiler_malloc; |
|
|
|
|
t.realloc = profiler_realloc; |
|
|
|
@ -214,6 +231,14 @@ void profiler_enable() {
|
|
|
|
|
g_mem_set_vtable(&t); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void profiler_finish() { |
|
|
|
|
for (profiler_entry *e = free_list; e != NULL;) { |
|
|
|
|
profiler_entry *prev = e; |
|
|
|
|
e = e->next; |
|
|
|
|
free(prev); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void profiler_dump() { |
|
|
|
|
if (!profiler_enabled) |
|
|
|
|
return; |
|
|
|
|