summaryrefslogtreecommitdiff
path: root/src/allocators-store.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2008-04-28 16:44:53 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2008-04-28 16:44:53 +0100
commitc3ba72816cee6507e2b8fefcddda2eb2b3e9bbd4 (patch)
tree456aa23c36440c06b63caf89c88e76df12d8ba6f /src/allocators-store.c
parent9db15748ff771cb9464742d78df56bbfb41f087d (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.c163
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);