|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
|
|
|
|
|
/* lighty memory profiler
|
|
|
|
|
/*
|
|
|
|
|
* lighty memory profiler |
|
|
|
|
* counts how many times malloc/realloc/free have been called and the amounts of bytes allocated/freed |
|
|
|
|
* TODO: move hashtable to utils.c, optimize hashtable? implementation is very basic |
|
|
|
|
*/ |
|
|
|
@ -19,7 +20,7 @@ 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 GMutex *profiler_mutex = NULL; |
|
|
|
|
static gboolean profiler_enabled = FALSE; |
|
|
|
|
static profiler_entry *free_list = NULL; |
|
|
|
|
|
|
|
|
@ -107,12 +108,12 @@ static gpointer profiler_try_malloc(gsize n_bytes) {
|
|
|
|
|
p = malloc(n_bytes); |
|
|
|
|
|
|
|
|
|
if (p) { |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_hashtable_insert(p, n_bytes); |
|
|
|
|
stats_mem.alloc_times++; |
|
|
|
|
stats_mem.alloc_bytes += n_bytes; |
|
|
|
|
stats_mem.inuse_bytes += n_bytes; |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return p; |
|
|
|
@ -132,27 +133,27 @@ static gpointer profiler_try_realloc(gpointer mem, gsize n_bytes) {
|
|
|
|
|
|
|
|
|
|
if (!mem) { |
|
|
|
|
p = malloc(n_bytes); |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
stats_mem.alloc_times++; |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
l = 0; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
p = realloc(p, n_bytes); |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_entry *e = profiler_hashtable_find(mem); |
|
|
|
|
l = e->len; |
|
|
|
|
profiler_hashtable_remove(mem); |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (p) { |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_hashtable_insert(p, n_bytes); |
|
|
|
|
stats_mem.realloc_times++; |
|
|
|
|
stats_mem.realloc_bytes += n_bytes; |
|
|
|
|
stats_mem.inuse_bytes += n_bytes - l; |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return p; |
|
|
|
@ -175,12 +176,12 @@ static gpointer profiler_calloc(gsize n_blocks, gsize n_bytes) {
|
|
|
|
|
p = calloc(1, l); |
|
|
|
|
|
|
|
|
|
if (p) { |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_hashtable_insert(p, l); |
|
|
|
|
stats_mem.calloc_times++; |
|
|
|
|
stats_mem.calloc_bytes += l; |
|
|
|
|
stats_mem.inuse_bytes += l; |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
assert(p); |
|
|
|
@ -192,13 +193,14 @@ static void profiler_free(gpointer mem) {
|
|
|
|
|
gsize *p = mem; |
|
|
|
|
|
|
|
|
|
assert(p); |
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_entry *e = profiler_hashtable_find(mem); |
|
|
|
|
stats_mem.free_times++; |
|
|
|
|
stats_mem.free_bytes += e->len; |
|
|
|
|
stats_mem.inuse_bytes -= e->len; |
|
|
|
|
profiler_hashtable_remove(mem); |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
g_mutex_free(profiler_mutex); |
|
|
|
|
free(p); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -209,6 +211,8 @@ void profiler_enable() {
|
|
|
|
|
if (profiler_enabled) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
profiler_mutex = g_mutex_new(); |
|
|
|
|
|
|
|
|
|
profiler_enabled = TRUE; |
|
|
|
|
|
|
|
|
|
profiler_hashtable_init(); |
|
|
|
@ -243,9 +247,9 @@ void profiler_dump() {
|
|
|
|
|
if (!profiler_enabled) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
g_static_mutex_lock(&profiler_mutex); |
|
|
|
|
g_mutex_lock(profiler_mutex); |
|
|
|
|
profiler_mem s = stats_mem; |
|
|
|
|
g_static_mutex_unlock(&profiler_mutex); |
|
|
|
|
g_mutex_unlock(profiler_mutex); |
|
|
|
|
|
|
|
|
|
g_print("--- memory profiler stats ---\n"); |
|
|
|
|
g_print("malloc(): called %" G_GUINT64_FORMAT " times, %" G_GUINT64_FORMAT " bytes total\n", s.alloc_times, s.alloc_bytes); |
|
|
|
|