libsysprof: add callgraph flag to merge similar processes

This is the backing implementation to allow for merging multiple processes
which have identical comm[] fields.
This commit is contained in:
Christian Hergert
2023-08-28 13:31:46 -07:00
parent 00c02f0f18
commit cdfae5f7b9
7 changed files with 36 additions and 15 deletions

View File

@ -345,7 +345,8 @@ _sysprof_callgraph_categorize (SysprofCallgraph *self,
static void
sysprof_callgraph_add_traceable (SysprofCallgraph *self,
SysprofDocumentTraceable *traceable,
guint list_model_index)
guint list_model_index,
gboolean merge_similar_processes)
{
SysprofAddressContext final_context;
SysprofCallgraphNode *node;
@ -421,7 +422,7 @@ sysprof_callgraph_add_traceable (SysprofCallgraph *self,
if ((self->flags & SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS) != 0)
symbols[n_symbols++] = _sysprof_document_thread_symbol (self->document, pid, tid);
symbols[n_symbols++] = _sysprof_document_process_symbol (self->document, pid);
symbols[n_symbols++] = _sysprof_document_process_symbol (self->document, pid, merge_similar_processes);
symbols[n_symbols++] = everything;
if (n_symbols > self->height)
@ -520,6 +521,7 @@ sysprof_callgraph_new_worker (GTask *task,
GCancellable *cancellable)
{
SysprofCallgraph *self = task_data;
gboolean merge_similar_processes;
guint n_items;
g_assert (G_IS_TASK (task));
@ -529,6 +531,8 @@ sysprof_callgraph_new_worker (GTask *task,
n_items = g_list_model_get_n_items (self->traceables);
merge_similar_processes = (self->flags & SYSPROF_CALLGRAPH_FLAGS_MERGE_SIMILAR_PROCESSES) != 0;
for (guint i = 0; i < n_items; i++)
{
g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (self->traceables, i);
@ -540,7 +544,7 @@ sysprof_callgraph_new_worker (GTask *task,
if (traceable == NULL)
break;
sysprof_callgraph_add_traceable (self, traceable, i);
sysprof_callgraph_add_traceable (self, traceable, i, merge_similar_processes);
}
/* Sort callgraph nodes alphabetically so that we can use them in the

View File

@ -93,13 +93,14 @@ typedef enum _SysprofCallgraphCategory
typedef enum _SysprofCallgraphFlags
{
SYSPROF_CALLGRAPH_FLAGS_NONE = 0,
SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS = 1 << 1,
SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES = 1 << 2,
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,
SYSPROF_CALLGRAPH_FLAGS_NONE = 0,
SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS = 1 << 1,
SYSPROF_CALLGRAPH_FLAGS_HIDE_SYSTEM_LIBRARIES = 1 << 2,
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,
SYSPROF_CALLGRAPH_FLAGS_MERGE_SIMILAR_PROCESSES = 1 << 7,
} SysprofCallgraphFlags;
SYSPROF_AVAILABLE_IN_ALL

View File

@ -164,7 +164,8 @@ sysprof_descendants_model_add_traceable (SysprofDescendantsModel *self,
SysprofDocument *document,
SysprofDocumentTraceable *traceable,
SysprofSymbol *from_symbol,
gboolean include_threads)
gboolean include_threads,
gboolean merge_similar_processes)
{
SysprofAddressContext final_context;
SysprofSymbol **symbols;
@ -193,7 +194,7 @@ sysprof_descendants_model_add_traceable (SysprofDescendantsModel *self,
symbols[n_symbols++] = _sysprof_document_thread_symbol (document, pid, thread_id);
}
symbols[n_symbols++] = _sysprof_document_process_symbol (document, pid);
symbols[n_symbols++] = _sysprof_document_process_symbol (document, pid, merge_similar_processes);
}
for (guint i = n_symbols; i > 0; i--)
@ -234,6 +235,7 @@ _sysprof_descendants_model_new (SysprofCallgraph *callgraph,
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GListModel) model = NULL;
gboolean include_threads;
gboolean merge_similar_processes;
guint n_items;
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (callgraph), NULL);
@ -251,13 +253,20 @@ _sysprof_descendants_model_new (SysprofCallgraph *callgraph,
g_assert (_sysprof_symbol_equal (self->root.summary->symbol, symbol));
include_threads = (callgraph->flags & SYSPROF_CALLGRAPH_FLAGS_INCLUDE_THREADS) != 0;
merge_similar_processes = (callgraph->flags & SYSPROF_CALLGRAPH_FLAGS_MERGE_SIMILAR_PROCESSES) != 0;
n_items = g_list_model_get_n_items (model);
for (guint i = 0; i < n_items; i++)
{
g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (model, i);
sysprof_descendants_model_add_traceable (self, document, traceable, symbol, include_threads);
sysprof_descendants_model_add_traceable (self,
document,
traceable,
symbol,
include_threads,
merge_similar_processes);
}
return G_LIST_MODEL (self);

View File

@ -75,7 +75,8 @@ GRefString *_sysprof_document_ref_string (SysprofDocument *self,
const char *name);
EggBitset *_sysprof_document_traceables (SysprofDocument *self);
SysprofSymbol *_sysprof_document_process_symbol (SysprofDocument *self,
int pid);
int pid,
gboolean want_shared);
SysprofSymbol *_sysprof_document_thread_symbol (SysprofDocument *self,
int pid,
int tid);

View File

@ -2106,7 +2106,8 @@ sysprof_document_callgraph_finish (SysprofDocument *self,
SysprofSymbol *
_sysprof_document_process_symbol (SysprofDocument *self,
int pid)
int pid,
gboolean want_shared)
{
SysprofProcessInfo *info;
@ -2120,6 +2121,9 @@ _sysprof_document_process_symbol (SysprofDocument *self,
if (info == NULL)
return self->missing_process;
if (want_shared && info->shared_symbol)
return info->shared_symbol;
if (info->symbol)
return info->symbol;

View File

@ -34,6 +34,7 @@ typedef struct _SysprofProcessInfo
SysprofMountNamespace *mount_namespace;
SysprofSymbolCache *symbol_cache;
SysprofSymbol *fallback_symbol;
SysprofSymbol *shared_symbol;
SysprofSymbol *symbol;
EggBitset *thread_ids;
int pid;

View File

@ -72,6 +72,7 @@ sysprof_process_info_finalize (gpointer data)
g_clear_object (&self->symbol_cache);
g_clear_object (&self->mount_namespace);
g_clear_object (&self->fallback_symbol);
g_clear_object (&self->shared_symbol);
g_clear_object (&self->symbol);
g_clear_pointer (&self->thread_ids, egg_bitset_unref);