mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
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:
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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));
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user