summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.c50
-rw-r--r--src/callgraph-store.c247
-rw-r--r--src/callgraph-treemap.c2
-rw-r--r--src/callgraph.c92
-rw-r--r--src/callgraph.h11
5 files changed, 250 insertions, 152 deletions
diff --git a/src/app.c b/src/app.c
index 3bdebc7..e455083 100644
--- a/src/app.c
+++ b/src/app.c
@@ -30,6 +30,7 @@ struct _app {
GtkWidget *timeline;
GtkWidget *statusbar;
+ gboolean discard_log;
GtkWidget *log_tv;
GtkTextBuffer *log;
GtkTextMark *log_end;
@@ -235,6 +236,7 @@ read_allocator (App *app, int fd, guint time)
guint magic;
guint last;
guint n;
+ guint total;
if (! readn (fd, &key, sizeof (key)))
return NULL;
@@ -330,11 +332,14 @@ read_allocator (App *app, int fd, guint time)
return NULL;
}
+ total = 0;
At->max_size_alloc = 0;
for (n = 0; n < G_N_ELEMENTS (At->size_allocs); n++) {
if (At->size_allocs[n] != 0)
At->max_size_alloc = n + 1;
+ total += At->size_allocs[n];
}
+ g_assert (total == At->n_allocs);
At->faults.next = NULL;
if (At->faults.tid != 0) {
@@ -751,36 +756,18 @@ refresh_clicked (GtkButton *button, App *app)
}
static void
-tree_map_selection_changed (GtkWidget *w, GtkTreeIter *iter, GtkTreeView *tv)
+call_graph_select_iter (GtkWidget *w, GtkTreeIter *iter, GtkTreeView *tv)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreePath *path;
- selection = gtk_tree_view_get_selection (tv);
- gtk_tree_selection_unselect_all (selection);
-
model = gtk_tree_view_get_model (tv);
- path = gtk_tree_model_get_path (model, iter);
-
- gtk_tree_view_expand_to_path (tv, path);
- gtk_tree_view_scroll_to_cell (tv, path, NULL, FALSE, 0., 0.);
- gtk_tree_path_free (path);
-
- gtk_tree_selection_select_iter (selection, iter);
-}
-
-static void
-ring_selection_changed (GtkWidget *w, GtkTreeIter *iter, GtkTreeView *tv)
-{
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreePath *path;
+ call_graph_store_update_tree_model ((CallGraphStore *) model);
selection = gtk_tree_view_get_selection (tv);
gtk_tree_selection_unselect_all (selection);
- model = gtk_tree_view_get_model (tv);
path = gtk_tree_model_get_path (model, iter);
gtk_tree_view_expand_to_path (tv, path);
@@ -820,11 +807,11 @@ main_window_create (App *app)
app);
g_signal_connect (app->allocations.tree_map, "selected",
- G_CALLBACK (tree_map_selection_changed),
+ G_CALLBACK (call_graph_select_iter),
app->allocations.call_graph);
g_signal_connect (app->allocations.ring, "selected",
- G_CALLBACK (ring_selection_changed),
+ G_CALLBACK (call_graph_select_iter),
app->allocations.call_graph);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (app->allocation_image.allocators));
@@ -966,6 +953,9 @@ tcp_events_server_cb (GIOChannel *source,
procmap_store_new (app->pid));
}
+ if (app->pid == 0 && app->child_terminated)
+ call_graph_store_update_tree_model (app->call_graph);
+
gdk_window_set_cursor (app->window->window, NULL);
gnet_tcp_socket_delete (client);
@@ -991,6 +981,9 @@ ensure_log (App *app)
GtkWidget *w, *sw, *label;
GtkTextIter iter;
+ if (app->discard_log)
+ return NULL;
+
if (app->log != NULL)
return app->log;
@@ -1051,8 +1044,10 @@ tcp_log_client_cb (GIOChannel *source,
}
}
- gtk_text_buffer_get_end_iter (log, &iter);
- gtk_text_buffer_insert (log, &iter, buf, ret);
+ if (log != NULL) {
+ gtk_text_buffer_get_end_iter (log, &iter);
+ gtk_text_buffer_insert (log, &iter, buf, ret);
+ }
} while (ret == sizeof (buf));
if (ret <= 0)
@@ -1185,6 +1180,7 @@ static void
reap_child (GPid pid, gint status, gpointer data)
{
App *app = data;
+
gtk_widget_set_sensitive (app->refresh_button, FALSE);
app->child_terminated = TRUE;
g_spawn_close_pid (pid);
@@ -1275,6 +1271,8 @@ int main
app.allocators_by_addr.nodes = g_new0 (Allocator *,
app.allocators_by_addr.size);
+ app.discard_log = TRUE;
+
window = main_window_create (&app);
g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
gtk_window_present (GTK_WINDOW (window));
@@ -1306,8 +1304,10 @@ int main
if (io != NULL) {
if (! load_allocators (io, &app)) {
g_warning ("Failed to load allocations from '%s'", argv[1]);
- } else
+ } else {
+ call_graph_store_update_tree_model (app.call_graph);
have_allocators = TRUE;
+ }
g_io_channel_unref (io);
}
if (! have_allocators) {
diff --git a/src/callgraph-store.c b/src/callgraph-store.c
index 38b0d99..869b0b3 100644
--- a/src/callgraph-store.c
+++ b/src/callgraph-store.c
@@ -29,6 +29,7 @@ typedef gboolean (*TraverseFunc) (CallGraphStore *, CallGraphFrame *, gpointer);
enum {
INSERTED = 1 << 0,
+ HAS_CHILD = 1 << 1,
};
static void
@@ -361,54 +362,66 @@ _call_graph_frame_key_cmp (gconstpointer A, gconstpointer B)
static CallGraphFrame *
_call_graph_frame_new (CallGraphStore *store,
- CallGraphFrame *parent,
- guint ip,
- const gchar *srcloc,
- const gchar *function)
+ const Allocator *A,
+ guint depth,
+ CallGraphFrame *parent)
{
CallGraphFrame *frame;
+ CallGraphFrame *node, **prev;
+ const AllocatorTime *At = A->time_tail;
+ guint index;
+ guint n, max;
frame = _call_graph_frame_alloc (store);
- frame->ip = ip;
- frame->frame = srcloc;
- frame->function = function;
+
+ frame->allocator = A;
+ frame->depth = depth;
+
+ frame->ip = A->ips[depth];
+ frame->frame = A->functions_srcloc[depth];
+ frame->function = A->functions[depth];
+
frame->parent = parent;
frame->next = store->frames;
store->frames = frame;
- if (parent != NULL) {
- CallGraphFrame *node, **prev;
- guint index;
-
- parent->children = _tree_insert (parent->children,
- &frame->node,
- _call_graph_frame_node_cmp);
-
- index = (ip ^ 6017773) % store->frames_by_ip.size;
- prev = &store->frames_by_ip.nodes[index];
- while ((node = *prev) != NULL && node->ip != ip)
- prev = &node->ht_next_by_ip;
- if (node != NULL) {
- frame->next_by_ip = node;
- *prev = node->ht_next_by_ip;
- node->ht_next_by_ip = NULL;
- }
- frame->ht_next_by_ip = store->frames_by_ip.nodes[index];
- store->frames_by_ip.nodes[index] = frame;
-
- index = (GPOINTER_TO_UINT (function) ^ 6017773) % store->frames_by_fn.size;
- prev = &store->frames_by_fn.nodes[index];
- while ((node = *prev) != NULL && node->function != function)
- prev = &node->ht_next_by_fn;
- if (node != NULL) {
- frame->next_by_fn = node;
- *prev = node->ht_next_by_fn;
- node->ht_next_by_fn = NULL;
- }
- frame->ht_next_by_fn = store->frames_by_fn.nodes[index];
- store->frames_by_fn.nodes[index] = frame;
+ frame->bytes = At->bytes;
+ frame->allocs = At->n_allocs;
+ frame->frees = At->n_frees;
+
+ max = At->max_size_alloc;
+ for (n = 0; n < max; n++)
+ frame->size_allocs[n] = At->size_allocs[n];
+
+
+ parent->children = _tree_insert (parent->children,
+ &frame->node,
+ _call_graph_frame_node_cmp);
+
+ index = (frame->ip ^ 6017773) % store->frames_by_ip.size;
+ prev = &store->frames_by_ip.nodes[index];
+ while ((node = *prev) != NULL && node->ip != frame->ip)
+ prev = &node->ht_next_by_ip;
+ if (node != NULL) {
+ frame->next_by_ip = node;
+ *prev = node->ht_next_by_ip;
+ node->ht_next_by_ip = NULL;
}
+ frame->ht_next_by_ip = store->frames_by_ip.nodes[index];
+ store->frames_by_ip.nodes[index] = frame;
+
+ index = (GPOINTER_TO_UINT (frame->function) ^ 6017773) % store->frames_by_fn.size;
+ prev = &store->frames_by_fn.nodes[index];
+ while ((node = *prev) != NULL && node->function != frame->function)
+ prev = &node->ht_next_by_fn;
+ if (node != NULL) {
+ frame->next_by_fn = node;
+ *prev = node->ht_next_by_fn;
+ node->ht_next_by_fn = NULL;
+ }
+ frame->ht_next_by_fn = store->frames_by_fn.nodes[index];
+ store->frames_by_fn.nodes[index] = frame;
return frame;
}
@@ -509,7 +522,7 @@ _call_graph_store_get_iter (GtkTreeModel *tree_model,
depth = gtk_tree_path_get_depth (path);
i = gtk_tree_path_get_indices (path);
- frame = self->root;
+ frame = &self->root;
for (n = 1; n < depth; n++) {
if ((guint) i[n] >= frame->n_filter)
return FALSE;
@@ -611,7 +624,7 @@ _call_graph_store_iter_children (GtkTreeModel *tree_model,
iter->user_data = frame->filter[0];
} else
- iter->user_data = self->root;
+ iter->user_data = &self->root;
return TRUE;
}
@@ -650,7 +663,7 @@ _call_graph_store_iter_nth_child (GtkTreeModel *tree_model,
if (n >= 1)
return FALSE;
iter->stamp = self->stamp;
- iter->user_data = self->root;
+ iter->user_data = &self->root;
return TRUE;
}
@@ -707,8 +720,9 @@ simple_hash_table_init (SimpleHashTable *ht, guint size)
static void
call_graph_store_init (CallGraphStore *self)
{
- self->root = _call_graph_frame_new (self, NULL, 0,
- "Everything", "Everything");
+ self->root.frame = self->root.function = "Everything";
+ self->root.depth = -1;
+ self->frames = &self->root;
/* XXX */
simple_hash_table_init (&self->frames_by_ip, 20000);
@@ -743,35 +757,22 @@ emit_tree_model_reorder (CallGraphFrame *frame,
{
gint new_order_stack[1024];
gint *new_order;
- guint n;
-
- g_print ("reorder\n");
+ guint n, m;
if (frame->old_n_filter > G_N_ELEMENTS (new_order_stack))
new_order = g_new (gint, frame->old_n_filter);
else
new_order = new_order_stack;
- for (n = 0; n < frame->old_n_filter; n++)
- new_order[n] = frame->old_filter[n]->index;
-
- /* exclude children we haven't inserted yet */
- if (frame->old_n_filter != frame->n_filter) {
- for (n = 0; n < frame->n_filter; n++) {
- if (! (frame->filter[n]->flags & INSERTED)) {
- guint m;
- for (m = 0; m < frame->old_n_filter; m++)
- if ((guint) new_order[m] >= frame->filter[n]->index)
- new_order[m]--;
- }
- }
- }
+ for (n = m = 0; n < frame->n_filter; n++)
+ if (frame->filter[n]->flags & INSERTED)
+ new_order[m++] = frame->filter[n]->old_index;
- /* XXX */
- n = frame->n_filter;
- frame->n_filter = frame->old_n_filter;
+ frame->n_filter = m;
- gtk_tree_model_rows_reordered (model, path, iter, new_order);
+ gtk_tree_model_rows_reordered (model, path,
+ frame->filter_parent == NULL ? NULL : iter,
+ new_order);
frame->n_filter = n;
@@ -785,14 +786,11 @@ emit_tree_model_signals (CallGraphFrame *frame, CallGraphStore *store)
GtkTreeModel *model = (GtkTreeModel *) store;
GtkTreeIter iter;
GtkTreePath *path;
+ guint n;
if (frame->stamp != store->stamp)
return;
- if (frame->is_alloc_fn)
- return _call_graph_frame_foreach_child (frame,
- (GFunc) emit_tree_model_signals, store);
-
iter.stamp = store->stamp;
iter.user_data = frame;
path = gtk_tree_model_get_path (model, &iter);
@@ -807,18 +805,76 @@ emit_tree_model_signals (CallGraphFrame *frame, CallGraphStore *store)
}
gtk_tree_model_row_changed (model, path, &iter);
+
+ if (! (frame->flags & HAS_CHILD) && frame->children != NULL) {
+ frame->flags |= HAS_CHILD;
+ gtk_tree_model_row_has_child_toggled (model, path, &iter);
+ }
} else {
- gtk_tree_model_row_inserted (model, path, &iter);
- if (frame->children != NULL)
+ if (frame->parent != NULL)
+ gtk_tree_model_row_inserted (model, path, &iter);
+ if (frame->children != NULL) {
+ frame->flags |= HAS_CHILD;
gtk_tree_model_row_has_child_toggled (model, path, &iter);
+ }
frame->flags |= INSERTED;
}
gtk_tree_path_free (path);
- _call_graph_frame_foreach_child (frame,
- (GFunc) emit_tree_model_signals, store);
+ for (n = 0; n < frame->n_filter; n++)
+ emit_tree_model_signals (frame->filter[n], store);
+}
+
+void
+call_graph_store_update_tree_model (CallGraphStore *store)
+{
+ CallGraphFrame *frame;
+
+ if (store->nodes == NULL)
+ return;
+
+ emit_tree_model_signals (&store->root, store);
+
+ for (frame = store->frames; frame != NULL; frame = frame->next) {
+ frame->old_filter = frame->filter;
+ frame->old_n_filter = frame->n_filter;
+ frame->old_index = frame->index;
+ }
+
+ g_free (store->old_nodes);
+ store->old_nodes = store->nodes;
+ store->nodes = NULL;
+}
+
+static void
+validate_sums (CallGraphFrame *frame)
+{
+ guint n;
+ guint allocs = 0, frees = 0;
+ guint64 bytes = 0;
+
+ for (n = 0; n < frame->n_filter; n++){
+ allocs += frame->filter[n]->allocs;
+ frees += frame->filter[n]->frees;
+ bytes += frame->filter[n]->bytes;
+ }
+
+ g_print ("%s\n", frame->frame);
+ g_print ("f->allocs=%d, f->frees=%d, f->bytes=%" G_GUINT64_FORMAT "\n",
+ frame->allocs, frame->frees, frame->bytes);
+ g_print ("allocs=%d, frees=%d, bytes=%" G_GUINT64_FORMAT "\n",
+ allocs, frees, bytes);
+
+ g_assert (allocs == frame->allocs);
+ g_assert (frees == frame->frees);
+ g_assert (bytes == frame->bytes);
+
+ g_assert (allocs >= frees);
+
+ for (n = 0; n < frame->n_filter; n++)
+ validate_sums (frame->filter[n]);
}
void
@@ -827,13 +883,11 @@ call_graph_store_update (CallGraphStore *store,
Allocator *allocators,
guint since)
{
- static AllocatorTime nil;
+ static const AllocatorTime nil;
Allocator *A;
CallGraphFrame *frame, *child, *eol;
guint n, new, updated;
- g_assert (store != NULL);
-
if (++store->stamp == 0)
store->stamp = 1;
@@ -853,7 +907,7 @@ call_graph_store_update (CallGraphStore *store,
if (At->max_size_alloc > store->max_size_alloc)
store->max_size_alloc = At->max_size_alloc;
- frame = store->root;
+ frame = &store->root;
_call_graph_frame_accumulate (frame, At, Ap);
frame->stamp = store->stamp;
for (n = 0; n < A->n_frames; n++) {
@@ -863,16 +917,17 @@ call_graph_store_update (CallGraphStore *store,
GUINT_TO_POINTER (A->ips[n]),
_call_graph_frame_key_cmp);
if (child == NULL) {
- child = _call_graph_frame_new (store, frame,
- A->ips[n],
- A->functions_srcloc[n],
- A->functions[n]);
+ child = _call_graph_frame_new (store, A, n, frame);
new++;
- }
+ } else
+ _call_graph_frame_accumulate (child, At, Ap);
+ child->stamp = store->stamp;
+
+ if (child->allocator == A)
+ break;
+ child->allocator = NULL;
+
frame = child;
- g_assert (frame != NULL);
- _call_graph_frame_accumulate (frame, At, Ap);
- frame->stamp = store->stamp;
}
updated++;
}
@@ -880,6 +935,8 @@ call_graph_store_update (CallGraphStore *store,
store->n_frames += new;
if (updated)
call_graph_store_filter (store, app);
+
+ validate_sums (&store->root);
}
static void
@@ -925,9 +982,11 @@ _call_graph_frame_add_children (CallGraphFrame *frame, CallGraphFrame *parent)
_call_graph_frame_foreach_child (frame,
(GFunc) _call_graph_frame_add_children, frame);
+#if 0
qsort (frame->filter,
frame->n_filter, sizeof (CallGraphFrame *),
_call_graph_frame_cmp);
+#endif
for (n = 0; n < frame->n_filter; n++)
frame->filter[n]->index = n;
@@ -952,21 +1011,22 @@ call_graph_store_filter (CallGraphStore *store, App *app)
guint serial = app_get_alloc_fns_serial (app);
guint n;
- root = store->root;
+ root = &store->root;
root->stamp = store->stamp; /* force an update of the root node */
//if (store->alloc_fns_serial != serial)
+#if 0
_call_graph_frame_foreach_child (root,
(GFunc) _call_graph_frame_is_alloc, app);
+#endif
store->alloc_fns_serial = serial;
- nodes = children = g_new (CallGraphFrame *, 2*store->n_frames);
+ nodes = store->nodes;
+ store->nodes = g_new (CallGraphFrame *, 2*store->n_frames);
+ children = store->nodes;
for (frame = store->frames; frame != NULL; frame = frame->next) {
- frame->old_filter = frame->filter;
- frame->old_n_filter = frame->n_filter;
-
if (frame->stamp == store->stamp) {
frame->n_filter = 0;
frame->filter = NULL;
@@ -986,24 +1046,23 @@ call_graph_store_filter (CallGraphStore *store, App *app)
children += frame->n_filter;
}
}
+ g_assert (children == store->nodes + store->n_frames);
+ g_free (nodes);
root->filter = children;
g_assert (root->n_filter == 0);
_call_graph_frame_foreach_child (root,
(GFunc) _call_graph_frame_add_filtered, root);
+#if 0
qsort (root->filter,
root->n_filter, sizeof (CallGraphFrame *),
_call_graph_frame_cmp);
+#endif
for (n = 0; n < root->n_filter; n++)
root->filter[n]->index = n;
- g_free (store->old_nodes);
- store->old_nodes = store->nodes;
- store->nodes = nodes;
-
- emit_tree_model_signals (store->root, store);
g_signal_emit (store, signals[FILTERED], 0);
}
diff --git a/src/callgraph-treemap.c b/src/callgraph-treemap.c
index 8d53cce..a0c6e1a 100644
--- a/src/callgraph-treemap.c
+++ b/src/callgraph-treemap.c
@@ -447,7 +447,7 @@ call_graph_tree_map_layout (CallGraphTreeMap *self)
rect.height = self->widget.allocation.height + 2*BORDER;
call_graph_tree_map_layout_subdivide (self,
- &self->layout, &rect, self->model->root);
+ &self->layout, &rect, &self->model->root);
call_graph_tree_map_layout_colour (self, &self->layout, 3., .6, .6);
}
diff --git a/src/callgraph.c b/src/callgraph.c
index 1b12cb6..95a78e8 100644
--- a/src/callgraph.c
+++ b/src/callgraph.c
@@ -51,8 +51,8 @@ call_graph_set_model (CallGraph *self, CallGraphStore *store)
GtkTreePath *path;
GtkTreeIter iter;
- iter.user_data = store->root;
- iter.stamp = 1;
+ iter.user_data = &store->root;
+ iter.stamp = store->stamp;
path = gtk_tree_model_get_path (model, &iter);
gtk_tree_view_expand_to_path (&self->tv, path);
@@ -243,44 +243,76 @@ call_graph_query_tooltip (GtkWidget *widget,
gtk_tooltip_set_custom (tooltip, GTK_WIDGET (w));
} else if (strcmp (title, "Frame") == 0) {
GString *string;
- CallGraphFrame *child;
const gchar *main_fn = app_get_main_function (app_get (widget));
guint n;
gchar *text;
- if (frame->n_filter == 0)
+ if (frame->function == main_fn)
return FALSE;
- string = g_string_new ("Top allocation site ");
-
- child = frame->filter[0];
n = 0;
- do {
- if (strcmp (child->frame, child->parent->frame)) {
- if (++n == 8)
- break;
- if (frame->function == main_fn)
+ if (frame->allocator == NULL) {
+ CallGraphFrame *child = frame->filter[0];
+ gchar calls[40];
+ gint len;
+
+ string = g_string_new ("Most frequent allocation site ");
+
+ do {
+ if (child->frame != child->parent->frame) {
+ if (++n == 8)
+ break;
+ if (frame->function == main_fn)
+ break;
+ }
+ if (child->allocator != NULL)
break;
- }
- child = child->filter[0];
- } while (child->n_filter);
- g_string_append_printf (string, "(%.0f%%):",
- child->allocs * 100. / frame->allocs);
- frame = frame->filter[0];
- n = 0;
- do {
- if (strcmp (frame->frame, frame->parent->frame)) {
- g_string_append_c (string, '\n');
- g_string_append_c (string, '\t');
- g_string_append (string, frame->frame);
- if (frame->function == main_fn)
- break;
- if (++n == 8)
- break;
- }
+ child = child->filter[0];
+ } while (child->n_filter);
+ len = g_snprintf (calls, 20, "%d", child->allocs);
+ pretty_print_number (calls, len, calls + 20);
+ g_string_append_printf (string, "%s (%.0f%%) calls:",
+ calls, child->allocs * 100. / frame->allocs);
+
frame = frame->filter[0];
- } while (frame->n_filter);
+ n = 0;
+ do {
+ if (frame->frame != frame->parent->frame) {
+ g_string_append_c (string, '\n');
+ g_string_append_c (string, '\t');
+ g_string_append (string, frame->frame);
+ if (frame->function == main_fn)
+ break;
+ if (++n == 8)
+ break;
+ }
+ if (frame->allocator != NULL)
+ break;
+
+ frame = frame->filter[0];
+ } while (frame->n_filter);
+ } else
+ string = g_string_new ("Called from:");
+
+ if (frame->function != main_fn && n < 8) {
+ const gchar *last_frame =frame->frame;
+ const Allocator *A = frame->allocator;
+ g_assert (A != NULL);
+ do {
+ const gchar *str = A->functions_srcloc[n + frame->depth + 1];
+ if (str != last_frame) {
+ g_string_append_c (string, '\n');
+ g_string_append_c (string, '\t');
+ g_string_append (string, str);
+ if (str == main_fn)
+ break;
+ if (++n == 8)
+ break;
+ last_frame = str;
+ }
+ } while (TRUE);
+ }
text = g_string_free (string, FALSE);
gtk_tooltip_set_text (tooltip, text);
diff --git a/src/callgraph.h b/src/callgraph.h
index ad07700..7f43823 100644
--- a/src/callgraph.h
+++ b/src/callgraph.h
@@ -20,9 +20,14 @@ struct _simple_hash_table {
struct _call_graph_frame {
guint ip;
+
+ const Allocator *allocator;
+ guint depth;
+
const gchar *frame;
const gchar *function;
gboolean is_alloc_fn;
+
guint64 bytes;
guint allocs;
guint frees;
@@ -33,7 +38,7 @@ struct _call_graph_frame {
guint stamp;
guint flags;
- guint index;
+ guint index, old_index;
CallGraphFrame **filter, **old_filter;
guint n_filter, old_n_filter;
CallGraphFrame *filter_parent;
@@ -50,7 +55,7 @@ struct _call_graph_store {
guint max_size_alloc;
guint stamp;
- CallGraphFrame *root, *frames;
+ CallGraphFrame root, *frames;
SimpleHashTable frames_by_ip;
SimpleHashTable frames_by_fn;
Chunk *frame_chunks;
@@ -81,6 +86,8 @@ call_graph_store_update (CallGraphStore *store,
App *app,
Allocator *allocators,
guint since);
+void
+call_graph_store_update_tree_model (CallGraphStore *store);
void
call_graph_store_sort (CallGraphStore *store);