sysprof: add support for bottom up stack traces

Keep the "All Processes" and "Process N" nodes, but reverse the stack
trace after that point.
This commit is contained in:
Christian Hergert
2023-07-13 21:23:21 -07:00
parent c059689da1
commit 6f76432a17
10 changed files with 106 additions and 11 deletions

View File

@ -226,16 +226,6 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
parent = &self->root; parent = &self->root;
/* If the first thing we see is a context switch, then there is
* nothing after it to account for. Just skip the symbol as it
* provides nothing to us in the callgraph.
*/
if (_sysprof_symbol_is_context_switch (symbols[0]))
{
symbols++;
n_symbols--;
}
for (guint i = n_symbols - 1; i > 0; i--) for (guint i = n_symbols - 1; i > 0; i--)
{ {
SysprofSymbol *symbol = symbols[i-1]; SysprofSymbol *symbol = symbols[i-1];
@ -279,6 +269,20 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
return parent; return parent;
} }
static void
reverse_symbols (SysprofSymbol **symbols,
guint n_symbols)
{
guint half = n_symbols / 2;
for (guint i = 0; i < half; i++)
{
SysprofSymbol *tmp = symbols[i];
symbols[i] = symbols[n_symbols-1-i];
symbols[n_symbols-1-i] = tmp;
}
}
static void static void
sysprof_callgraph_add_traceable (SysprofCallgraph *self, sysprof_callgraph_add_traceable (SysprofCallgraph *self,
SysprofDocumentTraceable *traceable, SysprofDocumentTraceable *traceable,
@ -332,6 +336,19 @@ sysprof_callgraph_add_traceable (SysprofCallgraph *self,
if (final_context == SYSPROF_ADDRESS_CONTEXT_KERNEL) if (final_context == SYSPROF_ADDRESS_CONTEXT_KERNEL)
symbols[n_symbols++] = _sysprof_document_kernel_symbol (self->document); symbols[n_symbols++] = _sysprof_document_kernel_symbol (self->document);
/* If the first thing we see is a context switch, then there is
* nothing after it to account for. Just skip the symbol as it
* provides nothing to us in the callgraph.
*/
if (_sysprof_symbol_is_context_switch (symbols[0]))
{
symbols++;
n_symbols--;
}
if ((self->flags & SYSPROF_CALLGRAPH_FLAGS_BOTTOM_UP) != 0)
reverse_symbols (symbols, n_symbols);
/* If the user requested thread-ids within each process, then /* If the user requested thread-ids within each process, then
* insert a symbol for that before the real stacks. * insert a symbol for that before the real stacks.
*/ */

View File

@ -67,6 +67,7 @@ typedef enum _SysprofCallgraphFlags
SYSPROF_CALLGRAPH_FLAGS_NONE = 0, SYSPROF_CALLGRAPH_FLAGS_NONE = 0,
SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS = 1 << 1, SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS = 1 << 1,
SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES = 1 << 2, SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES = 1 << 2,
SYSPROF_CALLGRAPH_FLAGS_BOTTOM_UP = 1 << 3,
} SysprofCallgraphFlags; } SysprofCallgraphFlags;
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL

View File

@ -50,6 +50,7 @@ struct _SysprofCallgraphView
guint reload_source; guint reload_source;
guint bottom_up : 1;
guint include_threads : 1; guint include_threads : 1;
guint hide_system_libraries : 1; guint hide_system_libraries : 1;
}; };

View File

@ -29,6 +29,7 @@
enum { enum {
PROP_0, PROP_0,
PROP_BOTTOM_UP,
PROP_CALLGRAPH, PROP_CALLGRAPH,
PROP_DOCUMENT, PROP_DOCUMENT,
PROP_HIDE_SYSTEM_LIBRARIES, PROP_HIDE_SYSTEM_LIBRARIES,
@ -336,6 +337,10 @@ sysprof_callgraph_view_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_BOTTOM_UP:
g_value_set_boolean (value, sysprof_callgraph_view_get_bottom_up (self));
break;
case PROP_CALLGRAPH: case PROP_CALLGRAPH:
g_value_set_object (value, sysprof_callgraph_view_get_callgraph (self)); g_value_set_object (value, sysprof_callgraph_view_get_callgraph (self));
break; break;
@ -375,6 +380,10 @@ sysprof_callgraph_view_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_BOTTOM_UP:
sysprof_callgraph_view_set_bottom_up (self, g_value_get_boolean (value));
break;
case PROP_DOCUMENT: case PROP_DOCUMENT:
sysprof_callgraph_view_set_document (self, g_value_get_object (value)); sysprof_callgraph_view_set_document (self, g_value_get_object (value));
break; break;
@ -406,6 +415,11 @@ sysprof_callgraph_view_class_init (SysprofCallgraphViewClass *klass)
object_class->get_property = sysprof_callgraph_view_get_property; object_class->get_property = sysprof_callgraph_view_get_property;
object_class->set_property = sysprof_callgraph_view_set_property; object_class->set_property = sysprof_callgraph_view_set_property;
properties[PROP_BOTTOM_UP] =
g_param_spec_boolean ("bottom-up", NULL, NULL,
FALSE,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties[PROP_CALLGRAPH] = properties[PROP_CALLGRAPH] =
g_param_spec_object ("callgraph", NULL, NULL, g_param_spec_object ("callgraph", NULL, NULL,
SYSPROF_TYPE_CALLGRAPH, SYSPROF_TYPE_CALLGRAPH,
@ -579,6 +593,9 @@ sysprof_callgraph_view_reload (SysprofCallgraphView *self)
if (self->hide_system_libraries) if (self->hide_system_libraries)
flags |= SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES; flags |= SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES;
if (self->bottom_up)
flags |= SYSPROF_CALLGRAPH_FLAGS_BOTTOM_UP;
sysprof_document_callgraph_async (self->document, sysprof_document_callgraph_async (self->document,
flags, flags,
self->traceables, self->traceables,
@ -713,6 +730,30 @@ sysprof_callgraph_view_get_callgraph (SysprofCallgraphView *self)
return self->callgraph; return self->callgraph;
} }
gboolean
sysprof_callgraph_view_get_bottom_up (SysprofCallgraphView *self)
{
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self), FALSE);
return self->bottom_up;
}
void
sysprof_callgraph_view_set_bottom_up (SysprofCallgraphView *self,
gboolean bottom_up)
{
g_return_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self));
bottom_up = !!bottom_up;
if (self->bottom_up != bottom_up)
{
self->bottom_up = bottom_up;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BOTTOM_UP]);
sysprof_callgraph_view_queue_reload (self);
}
}
gboolean gboolean
sysprof_callgraph_view_get_hide_system_libraries (SysprofCallgraphView *self) sysprof_callgraph_view_get_hide_system_libraries (SysprofCallgraphView *self)
{ {

View File

@ -50,6 +50,11 @@ SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_traceables (SysprofCallgraphView *self, void sysprof_callgraph_view_set_traceables (SysprofCallgraphView *self,
GListModel *model); GListModel *model);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_callgraph_view_get_bottom_up (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_bottom_up (SysprofCallgraphView *self,
gboolean bottom_up);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_callgraph_view_get_include_threads (SysprofCallgraphView *self); gboolean sysprof_callgraph_view_get_include_threads (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_include_threads (SysprofCallgraphView *self, void sysprof_callgraph_view_set_include_threads (SysprofCallgraphView *self,

View File

@ -42,12 +42,14 @@ struct _SysprofSession
SysprofTimeSpan selected_time; SysprofTimeSpan selected_time;
SysprofTimeSpan visible_time; SysprofTimeSpan visible_time;
guint bottom_up : 1;
guint include_threads : 1; guint include_threads : 1;
guint hide_system_libraries : 1; guint hide_system_libraries : 1;
}; };
enum { enum {
PROP_0, PROP_0,
PROP_BOTTOM_UP,
PROP_DOCUMENT, PROP_DOCUMENT,
PROP_DOCUMENT_TIME, PROP_DOCUMENT_TIME,
PROP_FILTER, PROP_FILTER,
@ -126,6 +128,10 @@ sysprof_session_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_BOTTOM_UP:
g_value_set_boolean (value, self->bottom_up);
break;
case PROP_DOCUMENT: case PROP_DOCUMENT:
g_value_set_object (value, sysprof_session_get_document (self)); g_value_set_object (value, sysprof_session_get_document (self));
break; break;
@ -181,6 +187,10 @@ sysprof_session_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_BOTTOM_UP:
self->bottom_up = g_value_get_boolean (value);
break;
case PROP_DOCUMENT: case PROP_DOCUMENT:
sysprof_session_set_document (self, g_value_get_object (value)); sysprof_session_set_document (self, g_value_get_object (value));
break; break;
@ -207,6 +217,11 @@ sysprof_session_class_init (SysprofSessionClass *klass)
object_class->get_property = sysprof_session_get_property; object_class->get_property = sysprof_session_get_property;
object_class->set_property = sysprof_session_set_property; object_class->set_property = sysprof_session_set_property;
properties [PROP_BOTTOM_UP] =
g_param_spec_boolean ("bottom-up", NULL, NULL,
FALSE,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties [PROP_DOCUMENT] = properties [PROP_DOCUMENT] =
g_param_spec_object ("document", NULL, NULL, g_param_spec_object ("document", NULL, NULL,
SYSPROF_TYPE_DOCUMENT, SYSPROF_TYPE_DOCUMENT,

View File

@ -76,6 +76,11 @@
<lookup name="session">SysprofMemorySection</lookup> <lookup name="session">SysprofMemorySection</lookup>
</lookup> </lookup>
</binding> </binding>
<binding name="bottom-up">
<lookup name="bottom-up" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup>
</lookup>
</binding>
<binding name="document"> <binding name="document">
<lookup name="document" type="SysprofSession"> <lookup name="document" type="SysprofSession">
<lookup name="session">SysprofMemorySection</lookup> <lookup name="session">SysprofMemorySection</lookup>

View File

@ -76,6 +76,11 @@
<lookup name="session">SysprofSamplesSection</lookup> <lookup name="session">SysprofSamplesSection</lookup>
</lookup> </lookup>
</binding> </binding>
<binding name="bottom-up">
<lookup name="bottom-up" type="SysprofSession">
<lookup name="session">SysprofSamplesSection</lookup>
</lookup>
</binding>
<binding name="document"> <binding name="document">
<lookup name="document" type="SysprofSession"> <lookup name="document" type="SysprofSession">
<lookup name="session">SysprofSamplesSection</lookup> <lookup name="session">SysprofSamplesSection</lookup>

View File

@ -139,8 +139,9 @@ sysprof_window_set_document (SysprofWindow *self,
SysprofDocument *document) SysprofDocument *document)
{ {
static const char *callgraph_actions[] = { static const char *callgraph_actions[] = {
"include-threads", "bottom-up",
"hide-system-libraries", "hide-system-libraries",
"include-threads",
}; };
g_assert (SYSPROF_IS_WINDOW (self)); g_assert (SYSPROF_IS_WINDOW (self));

View File

@ -225,6 +225,10 @@
<attribute name="label" translatable="yes">Include Threads</attribute> <attribute name="label" translatable="yes">Include Threads</attribute>
<attribute name="action">win.callgraph.include-threads</attribute> <attribute name="action">win.callgraph.include-threads</attribute>
</item> </item>
<item>
<attribute name="label" translatable="yes">Bottom Up</attribute>
<attribute name="action">win.callgraph.bottom-up</attribute>
</item>
</section> </section>
</menu> </menu>
</interface> </interface>