libsysprof-analyze: add summary augmentation capabilities

This allows us to have augmentation at the summary level so that things
like the weighted callgraph or memprof callgraph can add their respective
summary data up the chain of function calls.
This commit is contained in:
Christian Hergert
2023-06-09 11:19:40 -07:00
parent 900c39c0d8
commit 814c25d45a
4 changed files with 79 additions and 39 deletions

View File

@ -176,7 +176,7 @@ sysprof_callgraph_frame_get_symbol (SysprofCallgraphFrame *self)
if (self->callgraph == NULL)
return NULL;
return self->node->symbol;
return self->node->summary->symbol;
}
/**
@ -197,3 +197,23 @@ sysprof_callgraph_frame_get_augment (SysprofCallgraphFrame *self)
return sysprof_callgraph_get_augment (self->callgraph, self->node);
}
/**
* sysprof_callgraph_frame_get_summary_augment: (skip)
* @self: a #SysprofCallgraphFrame
*
* Gets the augmentation that was attached to the summary for
* the callgraph node's symbol.
*
* Returns: (nullable) (transfer none): the augmentation data
*/
gpointer
sysprof_callgraph_frame_get_summary_augment (SysprofCallgraphFrame *self)
{
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_FRAME (self), NULL);
if (self->callgraph == NULL)
return NULL;
return sysprof_callgraph_get_summary_augment (self->callgraph, self->node);
}

View File

@ -25,16 +25,26 @@
#include "sysprof-callgraph.h"
#include "sysprof-document.h"
#include "eggbitset.h"
G_BEGIN_DECLS
typedef struct _SysprofCallgraphSummary
{
SysprofSymbol *symbol;
EggBitset *traceables;
GPtrArray *callers;
gpointer augment;
} SysprofCallgraphSummary;
struct _SysprofCallgraphNode
{
SysprofCallgraphNode *parent;
SysprofCallgraphNode *prev;
SysprofCallgraphNode *next;
SysprofCallgraphNode *children;
SysprofSymbol *symbol;
gpointer augment;
SysprofCallgraphNode *parent;
SysprofCallgraphNode *prev;
SysprofCallgraphNode *next;
SysprofCallgraphNode *children;
SysprofCallgraphSummary *summary;
gpointer augment;
};
void _sysprof_callgraph_new_async (SysprofDocument *document,

View File

@ -38,8 +38,6 @@ struct _SysprofCallgraph
SysprofDocument *document;
GListModel *traceables;
SysprofSymbol *everything;
GHashTable *symbol_to_summary;
gsize augment_size;
@ -50,13 +48,6 @@ struct _SysprofCallgraph
SysprofCallgraphNode root;
};
typedef struct _SysprofCallgraphSummary
{
gpointer augment;
EggBitset *traceables;
GPtrArray *callers;
} SysprofCallgraphSummary;
static GType
sysprof_callgraph_get_item_type (GListModel *model)
{
@ -92,6 +83,8 @@ list_model_iface_init (GListModelInterface *iface)
G_DEFINE_FINAL_TYPE_WITH_CODE (SysprofCallgraph, sysprof_callgraph, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
static SysprofSymbol *everything;
static void
sysprof_callgraph_summary_free_all (SysprofCallgraphSummary *summary)
{
@ -122,6 +115,7 @@ sysprof_callgraph_get_summary (SysprofCallgraph *self,
summary->augment = NULL;
summary->traceables = egg_bitset_new_empty ();
summary->callers = g_ptr_array_new ();
summary->symbol = symbol;
g_hash_table_insert (self->symbol_to_summary, symbol, summary);
}
@ -173,7 +167,6 @@ sysprof_callgraph_finalize (GObject *object)
g_clear_object (&self->document);
g_clear_object (&self->traceables);
g_clear_object (&self->everything);
sysprof_callgraph_node_free (&self->root, FALSE);
@ -187,13 +180,13 @@ sysprof_callgraph_class_init (SysprofCallgraphClass *klass)
object_class->dispose = sysprof_callgraph_dispose;
object_class->finalize = sysprof_callgraph_finalize;
everything = _sysprof_symbol_new (g_ref_string_new_intern ("[Everything]"), NULL, NULL, 0, 0);
}
static void
sysprof_callgraph_init (SysprofCallgraph *self)
{
self->everything = _sysprof_symbol_new (g_ref_string_new_intern ("[Everything]"), NULL, NULL, 0, 0);
self->root.symbol = self->everything;
}
static void
@ -208,15 +201,13 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self,
iter != NULL && iter->parent != NULL;
iter = iter->parent)
{
SysprofCallgraphSummary *summary;
SysprofSymbol *parent_symbol = iter->parent->summary->symbol;
guint pos;
summary = g_hash_table_lookup (self->symbol_to_summary, iter->symbol);
egg_bitset_add (iter->summary->traceables, list_model_index);
egg_bitset_add (summary->traceables, list_model_index);
if (!g_ptr_array_find (summary->callers, iter->parent->symbol, &pos))
g_ptr_array_add (summary->callers, iter->parent->symbol);
if (!g_ptr_array_find (iter->summary->callers, parent_symbol, &pos))
g_ptr_array_add (iter->summary->callers, parent_symbol);
}
}
@ -230,7 +221,7 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
g_assert (SYSPROF_IS_CALLGRAPH (self));
g_assert (n_symbols >= 2);
g_assert (symbols[n_symbols-1] == self->everything);
g_assert (symbols[n_symbols-1] == everything);
parent = &self->root;
@ -255,10 +246,11 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
iter = iter->next)
{
g_assert (iter != NULL);
g_assert (iter->symbol != NULL);
g_assert (iter->summary != NULL);
g_assert (iter->summary->symbol != NULL);
g_assert (symbol != NULL);
if (_sysprof_symbol_equal (iter->symbol, symbol))
if (_sysprof_symbol_equal (iter->summary->symbol, symbol))
{
node = iter;
goto next_symbol;
@ -267,7 +259,7 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
/* Otherwise create a new node */
node = g_new0 (SysprofCallgraphNode, 1);
node->symbol = symbol;
node->summary = sysprof_callgraph_get_summary (self, symbol);
node->parent = parent;
node->next = parent->children;
if (parent->children)
@ -322,7 +314,7 @@ sysprof_callgraph_add_traceable (SysprofCallgraph *self,
if (final_context == SYSPROF_ADDRESS_CONTEXT_KERNEL)
symbols[n_symbols++] = _sysprof_document_kernel_symbol (self->document);
symbols[n_symbols++] = _sysprof_document_process_symbol (self->document, pid);
symbols[n_symbols++] = self->everything;
symbols[n_symbols++] = everything;
node = sysprof_callgraph_add_trace (self, symbols, n_symbols, list_model_index);
@ -391,6 +383,7 @@ _sysprof_callgraph_new_async (SysprofDocument *document,
self->augment_func_data = augment_func_data;
self->augment_func_data_destroy = augment_func_data_destroy;
self->symbol_to_summary = g_hash_table_new_full (NULL, NULL, NULL, summary_free);
self->root.summary = sysprof_callgraph_get_summary (self, everything);
task = g_task_new (NULL, cancellable, callback, user_data);
g_task_set_source_tag (task, _sysprof_callgraph_new_async);
@ -407,20 +400,34 @@ _sysprof_callgraph_new_finish (GAsyncResult *result,
return g_task_propagate_pointer (G_TASK (result), error);
}
gpointer
sysprof_callgraph_get_augment (SysprofCallgraph *callgraph,
SysprofCallgraphNode *node)
static inline gpointer
get_augmentation (SysprofCallgraph *self,
gpointer *augment_location)
{
if (callgraph->augment_size == 0)
if (self->augment_size == 0)
return NULL;
if (callgraph->augment_size <= GLIB_SIZEOF_VOID_P)
return &node->augment;
if (self->augment_size <= GLIB_SIZEOF_VOID_P)
return augment_location;
if (node->augment == NULL)
node->augment = g_malloc0 (callgraph->augment_size);
if (*augment_location == NULL)
*augment_location = g_malloc0 (self->augment_size);
return node->augment;
return *augment_location;
}
gpointer
sysprof_callgraph_get_augment (SysprofCallgraph *self,
SysprofCallgraphNode *node)
{
return get_augmentation (self, &node->augment);
}
gpointer
sysprof_callgraph_get_summary_augment (SysprofCallgraph *self,
SysprofCallgraphNode *node)
{
return get_augmentation (self, &node->summary->augment);
}
SysprofCallgraphNode *

View File

@ -66,6 +66,9 @@ SYSPROF_AVAILABLE_IN_ALL
gpointer sysprof_callgraph_get_augment (SysprofCallgraph *self,
SysprofCallgraphNode *node);
SYSPROF_AVAILABLE_IN_ALL
gpointer sysprof_callgraph_get_summary_augment (SysprofCallgraph *self,
SysprofCallgraphNode *node);
SYSPROF_AVAILABLE_IN_ALL
SysprofCallgraphNode *sysprof_callgraph_node_parent (SysprofCallgraphNode *node);
G_END_DECLS