diff --git a/src/libsysprof/sysprof-callgraph.c b/src/libsysprof/sysprof-callgraph.c index 1bdd5473..05e92415 100644 --- a/src/libsysprof/sysprof-callgraph.c +++ b/src/libsysprof/sysprof-callgraph.c @@ -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 diff --git a/src/libsysprof/sysprof-callgraph.h b/src/libsysprof/sysprof-callgraph.h index cce8ca5b..c4c6e913 100644 --- a/src/libsysprof/sysprof-callgraph.h +++ b/src/libsysprof/sysprof-callgraph.h @@ -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 diff --git a/src/libsysprof/sysprof-descendants-model.c b/src/libsysprof/sysprof-descendants-model.c index a5a5fcc3..7d6ea2ec 100644 --- a/src/libsysprof/sysprof-descendants-model.c +++ b/src/libsysprof/sysprof-descendants-model.c @@ -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); diff --git a/src/libsysprof/sysprof-document-private.h b/src/libsysprof/sysprof-document-private.h index 2e8a5ee5..01bc460d 100644 --- a/src/libsysprof/sysprof-document-private.h +++ b/src/libsysprof/sysprof-document-private.h @@ -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); diff --git a/src/libsysprof/sysprof-document.c b/src/libsysprof/sysprof-document.c index 632d201c..23fa12e4 100644 --- a/src/libsysprof/sysprof-document.c +++ b/src/libsysprof/sysprof-document.c @@ -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; diff --git a/src/libsysprof/sysprof-process-info-private.h b/src/libsysprof/sysprof-process-info-private.h index 2a9025e4..47cee773 100644 --- a/src/libsysprof/sysprof-process-info-private.h +++ b/src/libsysprof/sysprof-process-info-private.h @@ -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; diff --git a/src/libsysprof/sysprof-process-info.c b/src/libsysprof/sysprof-process-info.c index 6cba4b7b..fc35d981 100644 --- a/src/libsysprof/sysprof-process-info.c +++ b/src/libsysprof/sysprof-process-info.c @@ -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);