diff --git a/src/libsysprof/sysprof-callgraph.c b/src/libsysprof/sysprof-callgraph.c index e7576909..1bdd5473 100644 --- a/src/libsysprof/sysprof-callgraph.c +++ b/src/libsysprof/sysprof-callgraph.c @@ -459,8 +459,25 @@ sort_by_symbol_name (gconstpointer a, return g_utf8_collate (node_a->summary->symbol->name, node_b->summary->symbol->name); } +static int +sort_by_count (gconstpointer a, + gconstpointer b) +{ + const SysprofCallgraphNode *node_a = *(const SysprofCallgraphNode * const *)a; + const SysprofCallgraphNode *node_b = *(const SysprofCallgraphNode * const *)b; + + if (node_a->count > node_b->count) + return -1; + + if (node_a->count < node_b->count) + return 1; + + return 0; +} + static void -sort_children (SysprofCallgraphNode *node) +sort_children (SysprofCallgraphNode *node, + SysprofCallgraphFlags flags) { SysprofCallgraphNode **children; guint n_children = 0; @@ -471,7 +488,7 @@ sort_children (SysprofCallgraphNode *node) for (SysprofCallgraphNode *child = node->children; child; child = child->next) { - sort_children (child); + sort_children (child, flags); n_children++; } @@ -480,7 +497,10 @@ sort_children (SysprofCallgraphNode *node) children[i++] = child; children[i] = NULL; - qsort (children, n_children, sizeof (SysprofCallgraphNode *), sort_by_symbol_name); + if (flags & SYSPROF_CALLGRAPH_FLAGS_LEFT_HEAVY) + qsort (children, n_children, sizeof (SysprofCallgraphNode *), sort_by_count); + else + qsort (children, n_children, sizeof (SysprofCallgraphNode *), sort_by_symbol_name); node->children = children[0]; node->children->prev = NULL; @@ -526,7 +546,7 @@ sysprof_callgraph_new_worker (GTask *task, /* Sort callgraph nodes alphabetically so that we can use them in the * flamegraph without any further processing. */ - sort_children (&self->root); + sort_children (&self->root, self->flags); g_task_return_pointer (task, g_object_ref (self), g_object_unref); } diff --git a/src/libsysprof/sysprof-callgraph.h b/src/libsysprof/sysprof-callgraph.h index 247fcadb..cce8ca5b 100644 --- a/src/libsysprof/sysprof-callgraph.h +++ b/src/libsysprof/sysprof-callgraph.h @@ -99,6 +99,7 @@ typedef enum _SysprofCallgraphFlags SYSPROF_CALLGRAPH_FLAGS_BOTTOM_UP = 1 << 3, SYSPROF_CALLGRAPH_FLAGS_CATEGORIZE_FRAMES = 1 << 4, SYSPROF_CALLGRAPH_FLAGS_IGNORE_PROCESS_0 = 1 << 5, + SYSPROF_CALLGRAPH_FLAGS_LEFT_HEAVY = 1 << 6, } SysprofCallgraphFlags; SYSPROF_AVAILABLE_IN_ALL diff --git a/src/sysprof/sysprof-callgraph-view-private.h b/src/sysprof/sysprof-callgraph-view-private.h index 294b9474..20ddefb4 100644 --- a/src/sysprof/sysprof-callgraph-view-private.h +++ b/src/sysprof/sysprof-callgraph-view-private.h @@ -57,6 +57,7 @@ struct _SysprofCallgraphView guint hide_system_libraries : 1; guint ignore_process_0 : 1; guint include_threads : 1; + guint left_heavy : 1; }; struct _SysprofCallgraphViewClass diff --git a/src/sysprof/sysprof-callgraph-view.c b/src/sysprof/sysprof-callgraph-view.c index 58b3d6c2..ccd187c5 100644 --- a/src/sysprof/sysprof-callgraph-view.c +++ b/src/sysprof/sysprof-callgraph-view.c @@ -38,6 +38,7 @@ enum { PROP_HIDE_SYSTEM_LIBRARIES, PROP_IGNORE_PROCESS_0, PROP_INCLUDE_THREADS, + PROP_LEFT_HEAVY, PROP_TRACEABLES, PROP_UTILITY_SUMMARY, PROP_UTILITY_TRACEABLES, @@ -394,6 +395,10 @@ sysprof_callgraph_view_get_property (GObject *object, g_value_set_boolean (value, sysprof_callgraph_view_get_include_threads (self)); break; + case PROP_LEFT_HEAVY: + g_value_set_boolean (value, sysprof_callgraph_view_get_left_heavy (self)); + break; + case PROP_TRACEABLES: g_value_set_object (value, sysprof_callgraph_view_get_traceables (self)); break; @@ -445,6 +450,10 @@ sysprof_callgraph_view_set_property (GObject *object, sysprof_callgraph_view_set_include_threads (self, g_value_get_boolean (value)); break; + case PROP_LEFT_HEAVY: + sysprof_callgraph_view_set_left_heavy (self, g_value_get_boolean (value)); + break; + case PROP_TRACEABLES: sysprof_callgraph_view_set_traceables (self, g_value_get_object (value)); break; @@ -499,6 +508,11 @@ sysprof_callgraph_view_class_init (SysprofCallgraphViewClass *klass) FALSE, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + properties[PROP_LEFT_HEAVY] = + g_param_spec_boolean ("left-heavy", NULL, NULL, + FALSE, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + properties[PROP_TRACEABLES] = g_param_spec_object ("traceables", NULL, NULL, G_TYPE_LIST_MODEL, @@ -680,6 +694,9 @@ sysprof_callgraph_view_reload (SysprofCallgraphView *self) if (self->categorize_frames) flags |= SYSPROF_CALLGRAPH_FLAGS_CATEGORIZE_FRAMES; + if (self->left_heavy) + flags |= SYSPROF_CALLGRAPH_FLAGS_LEFT_HEAVY; + sysprof_document_callgraph_async (self->document, flags, self->traceables, @@ -933,3 +950,27 @@ sysprof_callgraph_view_set_ignore_process_0 (SysprofCallgraphView *self, sysprof_callgraph_view_queue_reload (self); } } + +gboolean +sysprof_callgraph_view_get_left_heavy (SysprofCallgraphView *self) +{ + g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self), FALSE); + + return self->left_heavy; +} + +void +sysprof_callgraph_view_set_left_heavy (SysprofCallgraphView *self, + gboolean left_heavy) +{ + g_return_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self)); + + left_heavy = !!left_heavy; + + if (self->left_heavy != left_heavy) + { + self->left_heavy = left_heavy; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LEFT_HEAVY]); + sysprof_callgraph_view_queue_reload (self); + } +} diff --git a/src/sysprof/sysprof-callgraph-view.h b/src/sysprof/sysprof-callgraph-view.h index 01748d9e..71e81fa7 100644 --- a/src/sysprof/sysprof-callgraph-view.h +++ b/src/sysprof/sysprof-callgraph-view.h @@ -58,6 +58,9 @@ void sysprof_callgraph_view_set_include_threads (SysprofCallg gboolean sysprof_callgraph_view_get_hide_system_libraries (SysprofCallgraphView *self); void sysprof_callgraph_view_set_hide_system_libraries (SysprofCallgraphView *self, gboolean hide_system_libraries); +gboolean sysprof_callgraph_view_get_left_heavy (SysprofCallgraphView *self); +void sysprof_callgraph_view_set_left_heavy (SysprofCallgraphView *self, + gboolean left_heavy); G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCallgraphView, g_object_unref) diff --git a/src/sysprof/sysprof-samples-section.ui b/src/sysprof/sysprof-samples-section.ui index 13594888..a3c246f7 100644 --- a/src/sysprof/sysprof-samples-section.ui +++ b/src/sysprof/sysprof-samples-section.ui @@ -94,6 +94,11 @@ SysprofSamplesSection + + + SysprofSamplesSection + + SysprofSamplesSection diff --git a/src/sysprof/sysprof-session.c b/src/sysprof/sysprof-session.c index c01854df..ac77c87e 100644 --- a/src/sysprof/sysprof-session.c +++ b/src/sysprof/sysprof-session.c @@ -43,6 +43,7 @@ struct _SysprofSession guint categorize_frames : 1; guint ignore_process_0 : 1; guint include_threads : 1; + guint left_heavy : 1; guint hide_system_libraries : 1; }; @@ -52,6 +53,7 @@ enum { PROP_DOCUMENT, PROP_DOCUMENT_TIME, PROP_FILTER, + PROP_LEFT_HEAVY, PROP_HIDE_SYSTEM_LIBRARIES, PROP_IGNORE_PROCESS_0, PROP_INCLUDE_THREADS, @@ -156,6 +158,10 @@ sysprof_session_get_property (GObject *object, g_value_set_boolean (value, self->include_threads); break; + case PROP_LEFT_HEAVY: + g_value_set_boolean (value, self->left_heavy); + break; + case PROP_SELECTED_TIME: g_value_set_boxed (value, sysprof_session_get_selected_time (self)); break; @@ -211,6 +217,10 @@ sysprof_session_set_property (GObject *object, self->include_threads = g_value_get_boolean (value); break; + case PROP_LEFT_HEAVY: + self->left_heavy = g_value_get_boolean (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -265,6 +275,11 @@ sysprof_session_class_init (SysprofSessionClass *klass) FALSE, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + properties [PROP_LEFT_HEAVY] = + g_param_spec_boolean ("left-heavy", NULL, NULL, + FALSE, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + properties [PROP_SELECTED_TIME] = g_param_spec_boxed ("selected-time", NULL, NULL, SYSPROF_TYPE_TIME_SPAN, diff --git a/src/sysprof/sysprof-window.c b/src/sysprof/sysprof-window.c index d6a5fb4e..12123d06 100644 --- a/src/sysprof/sysprof-window.c +++ b/src/sysprof/sysprof-window.c @@ -224,6 +224,7 @@ sysprof_window_set_document (SysprofWindow *self, "hide-system-libraries", "ignore-process-0", "include-threads", + "left-heavy", }; g_autofree char *title = NULL; g_autofree char *full_title = NULL; diff --git a/src/sysprof/sysprof-window.ui b/src/sysprof/sysprof-window.ui index 5eb96a25..a8a7a234 100644 --- a/src/sysprof/sysprof-window.ui +++ b/src/sysprof/sysprof-window.ui @@ -382,5 +382,12 @@ win.callgraph.ignore-process-0 +
+ Flamegraph + + Left Heavy + win.callgraph.left-heavy + +