libsysprof-analyze: add callgraph flags for thread-ids

This allows you to set a flag to show the thread id of what was recorded.

Use this to help disassociate similar threads in a process to figure out
which thread is consuming a majority of the Total time of that process.
This commit is contained in:
Christian Hergert
2023-06-14 15:11:56 -07:00
parent 54ecdc57cd
commit 5b929b8d5d
20 changed files with 206 additions and 538 deletions

View File

@ -43,11 +43,13 @@ callgraphview symbol {
}
callgraphview symbol.context-switch,
callgraphview symbol.process,
callgraphview symbol.thread,
callgraphview symbol.root,
callgraphview symbol.unwindable {
font-weight: 600;
}
callgraphview row:not(:selected) treeexpander expander:checked+box symbol.process,
callgraphview row:not(:selected) treeexpander expander:checked+box symbol.thread,
callgraphview row:not(:selected) treeexpander expander:checked+box symbol.root {
border-radius: 9999px;
background-color: alpha(currentColor, .05);

View File

@ -50,6 +50,8 @@ struct _SysprofCallgraphView
GCancellable *cancellable;
guint reload_source;
guint include_threads : 1;
};
struct _SysprofCallgraphViewClass

View File

@ -31,6 +31,7 @@ enum {
PROP_0,
PROP_CALLGRAPH,
PROP_DOCUMENT,
PROP_INCLUDE_THREADS,
PROP_TRACEABLES,
N_PROPS
};
@ -249,6 +250,7 @@ functions_selection_changed_cb (SysprofCallgraphView *self,
default:
case SYSPROF_SYMBOL_KIND_PROCESS:
case SYSPROF_SYMBOL_KIND_THREAD:
case SYSPROF_SYMBOL_KIND_CONTEXT_SWITCH:
case SYSPROF_SYMBOL_KIND_UNWINDABLE:
case SYSPROF_SYMBOL_KIND_USER:
@ -383,6 +385,10 @@ sysprof_callgraph_view_get_property (GObject *object,
g_value_set_object (value, sysprof_callgraph_view_get_document (self));
break;
case PROP_INCLUDE_THREADS:
g_value_set_boolean (value, sysprof_callgraph_view_get_include_threads (self));
break;
case PROP_TRACEABLES:
g_value_set_object (value, sysprof_callgraph_view_get_traceables (self));
break;
@ -406,6 +412,10 @@ sysprof_callgraph_view_set_property (GObject *object,
sysprof_callgraph_view_set_document (self, g_value_get_object (value));
break;
case PROP_INCLUDE_THREADS:
sysprof_callgraph_view_set_include_threads (self, g_value_get_boolean (value));
break;
case PROP_TRACEABLES:
sysprof_callgraph_view_set_traceables (self, g_value_get_object (value));
break;
@ -435,6 +445,11 @@ sysprof_callgraph_view_class_init (SysprofCallgraphViewClass *klass)
SYSPROF_TYPE_DOCUMENT,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties[PROP_INCLUDE_THREADS] =
g_param_spec_boolean ("include-threads", NULL, NULL,
FALSE,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
properties[PROP_TRACEABLES] =
g_param_spec_object ("traceables", NULL, NULL,
G_TYPE_LIST_MODEL,
@ -566,11 +581,17 @@ sysprof_callgraph_view_reload_cb (GObject *object,
static gboolean
sysprof_callgraph_view_reload (SysprofCallgraphView *self)
{
SysprofCallgraphFlags flags = 0;
g_assert (SYSPROF_IS_CALLGRAPH_VIEW (self));
g_clear_handle_id (&self->reload_source, g_source_remove);
if (self->include_threads)
flags |= SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS;
sysprof_document_callgraph_async (self->document,
flags,
self->traceables,
SYSPROF_CALLGRAPH_VIEW_GET_CLASS (self)->augment_size,
SYSPROF_CALLGRAPH_VIEW_GET_CLASS (self)->augment_func,
@ -702,3 +723,27 @@ sysprof_callgraph_view_get_callgraph (SysprofCallgraphView *self)
return self->callgraph;
}
gboolean
sysprof_callgraph_view_get_include_threads (SysprofCallgraphView *self)
{
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self), FALSE);
return self->include_threads;
}
void
sysprof_callgraph_view_set_include_threads (SysprofCallgraphView *self,
gboolean include_threads)
{
g_return_if_fail (SYSPROF_IS_CALLGRAPH_VIEW (self));
include_threads = !!include_threads;
if (self->include_threads != include_threads)
{
self->include_threads = include_threads;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INCLUDE_THREADS]);
sysprof_callgraph_view_queue_reload (self);
}
}

View File

@ -36,19 +36,24 @@ typedef struct _SysprofCallgraphView SysprofCallgraphView;
typedef struct _SysprofCallgraphViewClass SysprofCallgraphViewClass;
SYSPROF_AVAILABLE_IN_ALL
GType sysprof_callgraph_view_get_type (void) G_GNUC_CONST;
GType sysprof_callgraph_view_get_type (void) G_GNUC_CONST;
SYSPROF_AVAILABLE_IN_ALL
SysprofCallgraph *sysprof_callgraph_view_get_callgraph (SysprofCallgraphView *self);
SysprofCallgraph *sysprof_callgraph_view_get_callgraph (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL
SysprofDocument *sysprof_callgraph_view_get_document (SysprofCallgraphView *self);
SysprofDocument *sysprof_callgraph_view_get_document (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_document (SysprofCallgraphView *self,
SysprofDocument *document);
void sysprof_callgraph_view_set_document (SysprofCallgraphView *self,
SysprofDocument *document);
SYSPROF_AVAILABLE_IN_ALL
GListModel *sysprof_callgraph_view_get_traceables (SysprofCallgraphView *self);
GListModel *sysprof_callgraph_view_get_traceables (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_traceables (SysprofCallgraphView *self,
GListModel *model);
void sysprof_callgraph_view_set_traceables (SysprofCallgraphView *self,
GListModel *model);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_callgraph_view_get_include_threads (SysprofCallgraphView *self);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_callgraph_view_set_include_threads (SysprofCallgraphView *self,
gboolean include_threads);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCallgraphView, g_object_unref)

View File

@ -48,6 +48,7 @@ static const char *kind_classes[] = {
NULL,
"root",
"process",
"thread",
"context-switch",
"user",
"kernel",

View File

@ -28,8 +28,10 @@
static GMainLoop *main_loop;
static char *kallsyms_path;
static char *filename;
static gboolean include_threads;
static const GOptionEntry entries[] = {
{ "kallsyms", 'k', 0, G_OPTION_ARG_FILENAME, &kallsyms_path, "The path to kallsyms to use for decoding", "PATH" },
{ "threads", 't', 0, G_OPTION_ARG_NONE, &include_threads, "Include threads in the callgraph" },
{ 0 }
};
@ -101,6 +103,7 @@ main (int argc,
view = g_object_new (SYSPROF_TYPE_WEIGHTED_CALLGRAPH_VIEW,
"traceables", model,
"document", document,
"include-threads", include_threads,
NULL);
g_signal_connect_swapped (window,
"close-request",