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
+
+