diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-04-28 16:44:53 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2008-04-28 16:44:53 +0100 |
commit | c3ba72816cee6507e2b8fefcddda2eb2b3e9bbd4 (patch) | |
tree | 456aa23c36440c06b63caf89c88e76df12d8ba6f /src/allocators-store.c | |
parent | 9db15748ff771cb9464742d78df56bbfb41f087d (diff) |
Add a pie-chart to allocation callstack tooltip.
Include a pie-chart to visualize the fraction of the calls for each level
of the callstack.
Diffstat (limited to 'src/allocators-store.c')
-rw-r--r-- | src/allocators-store.c | 163 |
1 files changed, 149 insertions, 14 deletions
diff --git a/src/allocators-store.c b/src/allocators-store.c index e7d3a4d..0293c0f 100644 --- a/src/allocators-store.c +++ b/src/allocators-store.c @@ -22,9 +22,16 @@ #include "odin.h" #include "allocators.h" +#include <string.h> + +#ifndef _ +#define _(x) x +#endif + struct _allocators_store { GObject object; + gboolean cumulative; AllocatorsStoreSort sort; GCompareFunc sum_allocators_cmp; GPtrArray *allocators; @@ -38,6 +45,7 @@ struct _allocators_store { GList *filters; Chunk *sum_allocator_chunks; + Chunk *list_allocator_chunks; guint update; }; @@ -59,6 +67,39 @@ G_DEFINE_TYPE_WITH_CODE (AllocatorsStore, allocators_store, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, allocators_store_tree_model_init)) +enum { + PROP_0=0, + PROP_CUMULATIVE +}; + +static void +allocators_store_set_property (GObject *obj, guint id, const GValue *v, GParamSpec *spec) +{ + AllocatorsStore *self = (AllocatorsStore *) obj; + switch (id) { + case PROP_CUMULATIVE: + self->cumulative = g_value_get_boolean (v); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, spec); + break; + } +} + +static void +allocators_store_get_property (GObject *obj, guint id, GValue *v, GParamSpec *spec) +{ + AllocatorsStore *self = (AllocatorsStore *) obj; + switch (id) { + case PROP_CUMULATIVE: + g_value_set_boolean (v, self->cumulative); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, spec); + break; + } +} + static struct _sum_allocator * _sum_allocator_alloc (AllocatorsStore *store) @@ -86,6 +127,32 @@ _sum_allocator_alloc (AllocatorsStore *store) return mem; } +static GSList * +_list_allocator_alloc (AllocatorsStore *store) +{ + gpointer mem; + gsize size = sizeof (GSList); + +#ifndef G_ENABLE_DEBUG + Chunk *c = store->list_allocator_chunks; + if (c == NULL || c->used + size > c->size) { + guint len = size * (32<<10); + c = g_malloc (sizeof (Chunk) + len); + c->size = len; + c->used = 0; + c->next = store->list_allocator_chunks; + store->list_allocator_chunks = c; + } + + mem = c->mem + c->used; + c->used += size; +#else + mem = g_malloc (size); +#endif + + return mem; +} + static gint _sum_allocators_cmp_by_size (gconstpointer A, gconstpointer B) { @@ -160,6 +227,14 @@ allocators_store_finalize (GObject *obj) c = next; } + c = self->list_allocator_chunks; + self->list_allocator_chunks = NULL; + while (c != NULL) { + Chunk *next = c->next; + g_free (c); + c = next; + } + g_ptr_array_free (self->allocators, TRUE); g_free (self->ht.nodes); @@ -171,7 +246,20 @@ allocators_store_class_init (AllocatorsStoreClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; + object_class->set_property = allocators_store_set_property; + object_class->get_property = allocators_store_get_property; object_class->finalize = allocators_store_finalize; + + g_object_class_install_property (object_class, + PROP_CUMULATIVE, + g_param_spec_boolean ("cumulative", + _("Cumulative"), + _("Cumulative"), + TRUE, + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME | + G_PARAM_READWRITE)); } @@ -358,9 +446,11 @@ allocators_store_init (AllocatorsStore *self) } AllocatorsStore * -allocators_store_new (void) +allocators_store_new (gboolean cumulative) { - return g_object_new (allocators_store_get_type (), NULL); + return g_object_new (allocators_store_get_type (), + "cumulative", cumulative, + NULL); } void @@ -390,6 +480,12 @@ allocators_store_set_sort (AllocatorsStore *store, AllocatorsStoreSort sort) allocators_store_update (store); } +gboolean +allocators_store_is_cumulative (AllocatorsStore *store) +{ + return store->cumulative; +} + AllocatorsStoreSort allocators_store_get_sort (AllocatorsStore *store) { @@ -457,6 +553,7 @@ allocators_store_new_sum (AllocatorsStore *store, const gchar *fn) sum->sorted = FALSE; sum->blocks = NULL; sum->largest = NULL; + sum->largest_size = 0; sum->filter_serial = 0; sum->filtered = FALSE; @@ -466,6 +563,8 @@ allocators_store_new_sum (AllocatorsStore *store, const gchar *fn) sum->ht_next = store->ht.nodes[index]; store->ht.nodes[index] = sum; + memset (sum->ht, 0, sizeof (sum->ht)); + return sum; } @@ -473,6 +572,7 @@ void allocators_store_reset_sums (AllocatorsStore *store) { struct _sum_allocator *sum; + Chunk *c; if (store->update) { g_source_remove (store->update); @@ -491,6 +591,17 @@ allocators_store_reset_sums (AllocatorsStore *store) sum->sorted = FALSE; sum->largest = NULL; + sum->largest_size = 0; + + memset (sum->ht, 0, sizeof (sum->ht)); + } + + c = store->list_allocator_chunks; + store->list_allocator_chunks = NULL; + while (c != NULL) { + Chunk *next = c->next; + g_free (c); + c = next; } } @@ -643,10 +754,24 @@ allocators_store_add_filter (AllocatorsStore *store, return TRUE; } +static void +_sum_add_allocator (AllocatorsStore *store, struct _sum_allocator *sum, Allocator *A) +{ + guint index = ((gulong) A ^ 6017773UL) % G_N_ELEMENTS (sum->ht); + GSList *l = sum->ht[index]; + while (l != NULL && l->data != A) + l = l->next; + if (l == NULL) { + l = _list_allocator_alloc (store); + l->data = A; + l->next = sum->ht[index]; + sum->ht[index] = l; + } +} + void allocators_store_update_from_allocators (AllocatorsStore *store, - Allocator *allocators, - gboolean total) + Allocator *allocators) { Allocator *A; struct _sum_allocator *sum; @@ -654,27 +779,37 @@ allocators_store_update_from_allocators (AllocatorsStore *store, allocators_store_reset_sums (store); for (A = allocators; A != NULL; A = A->next) { + gsize size; + guint count; + if (A->time_tail->n_allocs == 0) continue; - if (! total && A->time_tail->n_allocs == A->time_tail->n_frees) + if (! store->cumulative && + A->time_tail->n_allocs == A->time_tail->n_frees) + { continue; + } sum = allocators_store_get_sum (store, A->alloc_fn); if (sum == NULL) sum = allocators_store_new_sum (store, A->alloc_fn); + _sum_add_allocator (store, sum, A); - if (sum->largest == NULL || - A->time_tail->bytes > sum->largest->time_tail->bytes) - sum->largest = A; + size = A->time_tail->bytes; + count = A->time_tail->n_allocs; + if (! store->cumulative) { + size -= A->time_tail->freed; + count -= A->time_tail->n_frees; + } - if (total) { - sum->size += A->time_tail->bytes; - sum->count += A->time_tail->n_allocs; - } else { - sum->size += A->time_tail->bytes - A->time_tail->freed; - sum->count += A->time_tail->n_allocs - A->time_tail->n_frees; + if (sum->largest == NULL || size > sum->largest_size) { + sum->largest = A; + sum->largest_size = size; } + + sum->size += size; + sum->count += count; } _allocators_store_update (store); |