mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-09 22:50:54 +00:00
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:
@ -176,7 +176,7 @@ sysprof_callgraph_frame_get_symbol (SysprofCallgraphFrame *self)
|
|||||||
if (self->callgraph == NULL)
|
if (self->callgraph == NULL)
|
||||||
return 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);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@ -25,16 +25,26 @@
|
|||||||
#include "sysprof-callgraph.h"
|
#include "sysprof-callgraph.h"
|
||||||
#include "sysprof-document.h"
|
#include "sysprof-document.h"
|
||||||
|
|
||||||
|
#include "eggbitset.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _SysprofCallgraphSummary
|
||||||
|
{
|
||||||
|
SysprofSymbol *symbol;
|
||||||
|
EggBitset *traceables;
|
||||||
|
GPtrArray *callers;
|
||||||
|
gpointer augment;
|
||||||
|
} SysprofCallgraphSummary;
|
||||||
|
|
||||||
struct _SysprofCallgraphNode
|
struct _SysprofCallgraphNode
|
||||||
{
|
{
|
||||||
SysprofCallgraphNode *parent;
|
SysprofCallgraphNode *parent;
|
||||||
SysprofCallgraphNode *prev;
|
SysprofCallgraphNode *prev;
|
||||||
SysprofCallgraphNode *next;
|
SysprofCallgraphNode *next;
|
||||||
SysprofCallgraphNode *children;
|
SysprofCallgraphNode *children;
|
||||||
SysprofSymbol *symbol;
|
SysprofCallgraphSummary *summary;
|
||||||
gpointer augment;
|
gpointer augment;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _sysprof_callgraph_new_async (SysprofDocument *document,
|
void _sysprof_callgraph_new_async (SysprofDocument *document,
|
||||||
|
|||||||
@ -38,8 +38,6 @@ struct _SysprofCallgraph
|
|||||||
SysprofDocument *document;
|
SysprofDocument *document;
|
||||||
GListModel *traceables;
|
GListModel *traceables;
|
||||||
|
|
||||||
SysprofSymbol *everything;
|
|
||||||
|
|
||||||
GHashTable *symbol_to_summary;
|
GHashTable *symbol_to_summary;
|
||||||
|
|
||||||
gsize augment_size;
|
gsize augment_size;
|
||||||
@ -50,13 +48,6 @@ struct _SysprofCallgraph
|
|||||||
SysprofCallgraphNode root;
|
SysprofCallgraphNode root;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _SysprofCallgraphSummary
|
|
||||||
{
|
|
||||||
gpointer augment;
|
|
||||||
EggBitset *traceables;
|
|
||||||
GPtrArray *callers;
|
|
||||||
} SysprofCallgraphSummary;
|
|
||||||
|
|
||||||
static GType
|
static GType
|
||||||
sysprof_callgraph_get_item_type (GListModel *model)
|
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_DEFINE_FINAL_TYPE_WITH_CODE (SysprofCallgraph, sysprof_callgraph, G_TYPE_OBJECT,
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
|
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
|
||||||
|
|
||||||
|
static SysprofSymbol *everything;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_callgraph_summary_free_all (SysprofCallgraphSummary *summary)
|
sysprof_callgraph_summary_free_all (SysprofCallgraphSummary *summary)
|
||||||
{
|
{
|
||||||
@ -122,6 +115,7 @@ sysprof_callgraph_get_summary (SysprofCallgraph *self,
|
|||||||
summary->augment = NULL;
|
summary->augment = NULL;
|
||||||
summary->traceables = egg_bitset_new_empty ();
|
summary->traceables = egg_bitset_new_empty ();
|
||||||
summary->callers = g_ptr_array_new ();
|
summary->callers = g_ptr_array_new ();
|
||||||
|
summary->symbol = symbol;
|
||||||
|
|
||||||
g_hash_table_insert (self->symbol_to_summary, symbol, summary);
|
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->document);
|
||||||
g_clear_object (&self->traceables);
|
g_clear_object (&self->traceables);
|
||||||
g_clear_object (&self->everything);
|
|
||||||
|
|
||||||
sysprof_callgraph_node_free (&self->root, FALSE);
|
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->dispose = sysprof_callgraph_dispose;
|
||||||
object_class->finalize = sysprof_callgraph_finalize;
|
object_class->finalize = sysprof_callgraph_finalize;
|
||||||
|
|
||||||
|
everything = _sysprof_symbol_new (g_ref_string_new_intern ("[Everything]"), NULL, NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_callgraph_init (SysprofCallgraph *self)
|
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
|
static void
|
||||||
@ -208,15 +201,13 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self,
|
|||||||
iter != NULL && iter->parent != NULL;
|
iter != NULL && iter->parent != NULL;
|
||||||
iter = iter->parent)
|
iter = iter->parent)
|
||||||
{
|
{
|
||||||
SysprofCallgraphSummary *summary;
|
SysprofSymbol *parent_symbol = iter->parent->summary->symbol;
|
||||||
guint pos;
|
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 (iter->summary->callers, parent_symbol, &pos))
|
||||||
|
g_ptr_array_add (iter->summary->callers, parent_symbol);
|
||||||
if (!g_ptr_array_find (summary->callers, iter->parent->symbol, &pos))
|
|
||||||
g_ptr_array_add (summary->callers, iter->parent->symbol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +221,7 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
|
|||||||
|
|
||||||
g_assert (SYSPROF_IS_CALLGRAPH (self));
|
g_assert (SYSPROF_IS_CALLGRAPH (self));
|
||||||
g_assert (n_symbols >= 2);
|
g_assert (n_symbols >= 2);
|
||||||
g_assert (symbols[n_symbols-1] == self->everything);
|
g_assert (symbols[n_symbols-1] == everything);
|
||||||
|
|
||||||
parent = &self->root;
|
parent = &self->root;
|
||||||
|
|
||||||
@ -255,10 +246,11 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
|
|||||||
iter = iter->next)
|
iter = iter->next)
|
||||||
{
|
{
|
||||||
g_assert (iter != NULL);
|
g_assert (iter != NULL);
|
||||||
g_assert (iter->symbol != NULL);
|
g_assert (iter->summary != NULL);
|
||||||
|
g_assert (iter->summary->symbol != NULL);
|
||||||
g_assert (symbol != NULL);
|
g_assert (symbol != NULL);
|
||||||
|
|
||||||
if (_sysprof_symbol_equal (iter->symbol, symbol))
|
if (_sysprof_symbol_equal (iter->summary->symbol, symbol))
|
||||||
{
|
{
|
||||||
node = iter;
|
node = iter;
|
||||||
goto next_symbol;
|
goto next_symbol;
|
||||||
@ -267,7 +259,7 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
|
|||||||
|
|
||||||
/* Otherwise create a new node */
|
/* Otherwise create a new node */
|
||||||
node = g_new0 (SysprofCallgraphNode, 1);
|
node = g_new0 (SysprofCallgraphNode, 1);
|
||||||
node->symbol = symbol;
|
node->summary = sysprof_callgraph_get_summary (self, symbol);
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
node->next = parent->children;
|
node->next = parent->children;
|
||||||
if (parent->children)
|
if (parent->children)
|
||||||
@ -322,7 +314,7 @@ 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);
|
||||||
symbols[n_symbols++] = _sysprof_document_process_symbol (self->document, pid);
|
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);
|
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 = augment_func_data;
|
||||||
self->augment_func_data_destroy = augment_func_data_destroy;
|
self->augment_func_data_destroy = augment_func_data_destroy;
|
||||||
self->symbol_to_summary = g_hash_table_new_full (NULL, NULL, NULL, summary_free);
|
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);
|
task = g_task_new (NULL, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, _sysprof_callgraph_new_async);
|
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);
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpointer
|
static inline gpointer
|
||||||
sysprof_callgraph_get_augment (SysprofCallgraph *callgraph,
|
get_augmentation (SysprofCallgraph *self,
|
||||||
SysprofCallgraphNode *node)
|
gpointer *augment_location)
|
||||||
{
|
{
|
||||||
if (callgraph->augment_size == 0)
|
if (self->augment_size == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (callgraph->augment_size <= GLIB_SIZEOF_VOID_P)
|
if (self->augment_size <= GLIB_SIZEOF_VOID_P)
|
||||||
return &node->augment;
|
return augment_location;
|
||||||
|
|
||||||
if (node->augment == NULL)
|
if (*augment_location == NULL)
|
||||||
node->augment = g_malloc0 (callgraph->augment_size);
|
*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 *
|
SysprofCallgraphNode *
|
||||||
|
|||||||
@ -66,6 +66,9 @@ SYSPROF_AVAILABLE_IN_ALL
|
|||||||
gpointer sysprof_callgraph_get_augment (SysprofCallgraph *self,
|
gpointer sysprof_callgraph_get_augment (SysprofCallgraph *self,
|
||||||
SysprofCallgraphNode *node);
|
SysprofCallgraphNode *node);
|
||||||
SYSPROF_AVAILABLE_IN_ALL
|
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);
|
SysprofCallgraphNode *sysprof_callgraph_node_parent (SysprofCallgraphNode *node);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
Reference in New Issue
Block a user