diff --git a/src/libsysprof/sysprof-callgraph.c b/src/libsysprof/sysprof-callgraph.c index 561c4d6b..94d0c8a4 100644 --- a/src/libsysprof/sysprof-callgraph.c +++ b/src/libsysprof/sysprof-callgraph.c @@ -445,6 +445,50 @@ sysprof_callgraph_add_traceable (SysprofCallgraph *self, _sysprof_callgraph_categorize (self, node); } +static int +sort_by_symbol_name (gconstpointer a, + gconstpointer b) +{ + const SysprofCallgraphNode *node_a = *(const SysprofCallgraphNode * const *)a; + const SysprofCallgraphNode *node_b = *(const SysprofCallgraphNode * const *)b; + + return g_utf8_collate (node_a->summary->symbol->name, node_b->summary->symbol->name); +} + +static void +sort_children (SysprofCallgraphNode *node) +{ + SysprofCallgraphNode **children; + guint n_children = 0; + guint i = 0; + + if (node->children == NULL) + return; + + for (SysprofCallgraphNode *child = node->children; child; child = child->next) + { + sort_children (child); + n_children++; + } + + children = g_alloca (sizeof (SysprofCallgraphNode *) * (n_children + 1)); + for (SysprofCallgraphNode *child = node->children; child; child = child->next) + children[i++] = child; + children[i] = NULL; + + qsort (children, n_children, sizeof (SysprofCallgraphNode *), sort_by_symbol_name); + + node->children = children[0]; + node->children->prev = NULL; + node->children->next = children[1]; + + for (i = 1; i < n_children; i++) + { + children[i]->next = children[i+1]; + children[i]->prev = children[i-1]; + } +} + static void sysprof_callgraph_new_worker (GTask *task, gpointer source_object, @@ -475,6 +519,11 @@ sysprof_callgraph_new_worker (GTask *task, sysprof_callgraph_add_traceable (self, traceable, i); } + /* Sort callgraph nodes alphabetically so that we can use them in the + * flamegraph without any further processing. + */ + sort_children (&self->root); + g_task_return_pointer (task, g_object_ref (self), g_object_unref); } diff --git a/src/sysprof/sysprof-flame-graph.c b/src/sysprof/sysprof-flame-graph.c index 71904f7f..c4471df2 100644 --- a/src/sysprof/sysprof-flame-graph.c +++ b/src/sysprof/sysprof-flame-graph.c @@ -47,16 +47,6 @@ G_DEFINE_FINAL_TYPE (SysprofFlameGraph, sysprof_flame_graph, GTK_TYPE_WIDGET) static GParamSpec *properties [N_PROPS]; -static int -compare_node (gconstpointer a, - gconstpointer b) -{ - const SysprofCallgraphNode *node_a = *(const SysprofCallgraphNode * const *)a; - const SysprofCallgraphNode *node_b = *(const SysprofCallgraphNode * const *)b; - - return strcmp (node_a->summary->symbol->name, node_b->summary->symbol->name); -} - static void sysprof_flame_graph_snapshot_node (GtkSnapshot *snapshot, SysprofCallgraphNode *node, @@ -105,31 +95,18 @@ sysprof_flame_graph_snapshot_node (GtkSnapshot *snapshot, if (node->children != NULL) { - SysprofCallgraphNode **children; graphene_rect_t child_area; guint64 weight = 0; - guint n_children = 0; - guint i = 0; child_area.origin.x = area->origin.x; child_area.origin.y = area->origin.y; child_area.size.height = area->size.height - ROW_HEIGHT - 1; for (SysprofCallgraphNode *child = node->children; child; child = child->next) - { - weight += child->count; - n_children++; - } + weight += child->count; - children = g_alloca (sizeof (SysprofCallgraphNode *) * n_children); for (SysprofCallgraphNode *child = node->children; child; child = child->next) - children[i++] = child; - - qsort (children, n_children, sizeof (SysprofCallgraphNode *), compare_node); - - for (i = 0; i < n_children; i++) { - SysprofCallgraphNode *child = children[i]; double ratio = child->count / (double)weight; double width;