mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
libsysprof-analyze: use summary struct for symbol information
We still need to figure out the right way to plumb in the augmentation data so that things that need to walk up the chain are possible, but this first gets things in order to do that.
This commit is contained in:
@ -40,9 +40,7 @@ struct _SysprofCallgraph
|
|||||||
|
|
||||||
SysprofSymbol *everything;
|
SysprofSymbol *everything;
|
||||||
|
|
||||||
GHashTable *symbol_to_bitset;
|
GHashTable *symbol_to_summary;
|
||||||
|
|
||||||
GHashTable *callers;
|
|
||||||
|
|
||||||
gsize augment_size;
|
gsize augment_size;
|
||||||
SysprofAugmentationFunc augment_func;
|
SysprofAugmentationFunc augment_func;
|
||||||
@ -52,6 +50,13 @@ 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)
|
||||||
{
|
{
|
||||||
@ -87,6 +92,43 @@ 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 void
|
||||||
|
sysprof_callgraph_summary_free_all (SysprofCallgraphSummary *summary)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&summary->augment, g_free);
|
||||||
|
g_clear_pointer (&summary->callers, g_ptr_array_unref);
|
||||||
|
g_clear_pointer (&summary->traceables, egg_bitset_unref);
|
||||||
|
g_free (summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sysprof_callgraph_summary_free_self (SysprofCallgraphSummary *summary)
|
||||||
|
{
|
||||||
|
summary->augment = NULL;
|
||||||
|
g_clear_pointer (&summary->callers, g_ptr_array_unref);
|
||||||
|
g_clear_pointer (&summary->traceables, egg_bitset_unref);
|
||||||
|
g_free (summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline SysprofCallgraphSummary *
|
||||||
|
sysprof_callgraph_get_summary (SysprofCallgraph *self,
|
||||||
|
SysprofSymbol *symbol)
|
||||||
|
{
|
||||||
|
SysprofCallgraphSummary *summary;
|
||||||
|
|
||||||
|
if G_UNLIKELY (!(summary = g_hash_table_lookup (self->symbol_to_summary, symbol)))
|
||||||
|
{
|
||||||
|
summary = g_new0 (SysprofCallgraphSummary, 1);
|
||||||
|
summary->augment = NULL;
|
||||||
|
summary->traceables = egg_bitset_new_empty ();
|
||||||
|
summary->callers = g_ptr_array_new ();
|
||||||
|
|
||||||
|
g_hash_table_insert (self->symbol_to_summary, symbol, summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysprof_callgraph_node_free (SysprofCallgraphNode *node,
|
sysprof_callgraph_node_free (SysprofCallgraphNode *node,
|
||||||
gboolean free_self)
|
gboolean free_self)
|
||||||
@ -127,8 +169,7 @@ sysprof_callgraph_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
SysprofCallgraph *self = (SysprofCallgraph *)object;
|
SysprofCallgraph *self = (SysprofCallgraph *)object;
|
||||||
|
|
||||||
g_clear_pointer (&self->callers, g_hash_table_unref);
|
g_clear_pointer (&self->symbol_to_summary, g_hash_table_unref);
|
||||||
g_clear_pointer (&self->symbol_to_bitset, g_hash_table_unref);
|
|
||||||
|
|
||||||
g_clear_object (&self->document);
|
g_clear_object (&self->document);
|
||||||
g_clear_object (&self->traceables);
|
g_clear_object (&self->traceables);
|
||||||
@ -152,8 +193,6 @@ 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->everything = _sysprof_symbol_new (g_ref_string_new_intern ("[Everything]"), NULL, NULL, 0, 0);
|
||||||
self->callers = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_ptr_array_unref);
|
|
||||||
self->symbol_to_bitset = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)egg_bitset_unref);
|
|
||||||
self->root.symbol = self->everything;
|
self->root.symbol = self->everything;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,39 +201,22 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self,
|
|||||||
SysprofCallgraphNode *node,
|
SysprofCallgraphNode *node,
|
||||||
guint list_model_index)
|
guint list_model_index)
|
||||||
{
|
{
|
||||||
GHashTable *hash;
|
|
||||||
|
|
||||||
g_assert (SYSPROF_IS_CALLGRAPH (self));
|
g_assert (SYSPROF_IS_CALLGRAPH (self));
|
||||||
g_assert (node != NULL);
|
g_assert (node != NULL);
|
||||||
|
|
||||||
hash = self->callers;
|
|
||||||
|
|
||||||
for (const SysprofCallgraphNode *iter = node;
|
for (const SysprofCallgraphNode *iter = node;
|
||||||
iter != NULL && iter->parent != NULL;
|
iter != NULL && iter->parent != NULL;
|
||||||
iter = iter->parent)
|
iter = iter->parent)
|
||||||
{
|
{
|
||||||
GPtrArray *callers;
|
SysprofCallgraphSummary *summary;
|
||||||
EggBitset *bitset;
|
|
||||||
guint pos;
|
guint pos;
|
||||||
|
|
||||||
if (!(callers = g_hash_table_lookup (hash, iter->symbol)))
|
summary = g_hash_table_lookup (self->symbol_to_summary, iter->symbol);
|
||||||
{
|
|
||||||
callers = g_ptr_array_new ();
|
|
||||||
g_hash_table_insert (hash, iter->symbol, callers);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(bitset = g_hash_table_lookup (self->symbol_to_bitset, iter->symbol)))
|
egg_bitset_add (summary->traceables, list_model_index);
|
||||||
{
|
|
||||||
bitset = egg_bitset_new_empty ();
|
|
||||||
g_hash_table_insert (self->symbol_to_bitset, iter->symbol, bitset);
|
|
||||||
}
|
|
||||||
|
|
||||||
egg_bitset_add (bitset, list_model_index);
|
if (!g_ptr_array_find (summary->callers, iter->parent->symbol, &pos))
|
||||||
|
g_ptr_array_add (summary->callers, iter->parent->symbol);
|
||||||
g_assert (iter->parent->symbol != NULL);
|
|
||||||
|
|
||||||
if (!g_ptr_array_find (callers, iter->parent->symbol, &pos))
|
|
||||||
g_ptr_array_add (callers, iter->parent->symbol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,11 +372,17 @@ _sysprof_callgraph_new_async (SysprofDocument *document,
|
|||||||
{
|
{
|
||||||
g_autoptr(SysprofCallgraph) self = NULL;
|
g_autoptr(SysprofCallgraph) self = NULL;
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GTask) task = NULL;
|
||||||
|
GDestroyNotify summary_free;
|
||||||
|
|
||||||
g_return_if_fail (SYSPROF_IS_DOCUMENT (document));
|
g_return_if_fail (SYSPROF_IS_DOCUMENT (document));
|
||||||
g_return_if_fail (G_IS_LIST_MODEL (traceables));
|
g_return_if_fail (G_IS_LIST_MODEL (traceables));
|
||||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
if (augment_size > GLIB_SIZEOF_VOID_P)
|
||||||
|
summary_free = (GDestroyNotify)sysprof_callgraph_summary_free_all;
|
||||||
|
else
|
||||||
|
summary_free = (GDestroyNotify)sysprof_callgraph_summary_free_self;
|
||||||
|
|
||||||
self = g_object_new (SYSPROF_TYPE_CALLGRAPH, NULL);
|
self = g_object_new (SYSPROF_TYPE_CALLGRAPH, NULL);
|
||||||
self->document = g_object_ref (document);
|
self->document = g_object_ref (document);
|
||||||
self->traceables = g_object_ref (traceables);
|
self->traceables = g_object_ref (traceables);
|
||||||
@ -362,6 +390,7 @@ _sysprof_callgraph_new_async (SysprofDocument *document,
|
|||||||
self->augment_func = augment_func;
|
self->augment_func = augment_func;
|
||||||
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);
|
||||||
|
|
||||||
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);
|
||||||
@ -384,7 +413,8 @@ sysprof_callgraph_get_augment (SysprofCallgraph *callgraph,
|
|||||||
{
|
{
|
||||||
if (callgraph->augment_size == 0)
|
if (callgraph->augment_size == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
else if (callgraph->augment_size <= GLIB_SIZEOF_VOID_P)
|
|
||||||
|
if (callgraph->augment_size <= GLIB_SIZEOF_VOID_P)
|
||||||
return &node->augment;
|
return &node->augment;
|
||||||
|
|
||||||
if (node->augment == NULL)
|
if (node->augment == NULL)
|
||||||
@ -412,9 +442,9 @@ GListModel *
|
|||||||
sysprof_callgraph_list_callers (SysprofCallgraph *self,
|
sysprof_callgraph_list_callers (SysprofCallgraph *self,
|
||||||
SysprofCallgraphFrame *frame)
|
SysprofCallgraphFrame *frame)
|
||||||
{
|
{
|
||||||
|
SysprofCallgraphSummary *summary;
|
||||||
SysprofSymbol *symbol;
|
SysprofSymbol *symbol;
|
||||||
GListStore *store;
|
GListStore *store;
|
||||||
GPtrArray *callers;
|
|
||||||
|
|
||||||
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL);
|
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL);
|
||||||
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_FRAME (frame), NULL);
|
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_FRAME (frame), NULL);
|
||||||
@ -422,8 +452,8 @@ sysprof_callgraph_list_callers (SysprofCallgraph *self,
|
|||||||
store = g_list_store_new (SYSPROF_TYPE_SYMBOL);
|
store = g_list_store_new (SYSPROF_TYPE_SYMBOL);
|
||||||
symbol = sysprof_callgraph_frame_get_symbol (frame);
|
symbol = sysprof_callgraph_frame_get_symbol (frame);
|
||||||
|
|
||||||
if ((callers = g_hash_table_lookup (self->callers, symbol)))
|
if ((summary = g_hash_table_lookup (self->symbol_to_summary, symbol)))
|
||||||
g_list_store_splice (store, 0, 0, callers->pdata, callers->len);
|
g_list_store_splice (store, 0, 0, summary->callers->pdata, summary->callers->len);
|
||||||
|
|
||||||
return G_LIST_MODEL (store);
|
return G_LIST_MODEL (store);
|
||||||
}
|
}
|
||||||
@ -442,13 +472,13 @@ GListModel *
|
|||||||
sysprof_callgraph_list_traceables_for_symbol (SysprofCallgraph *self,
|
sysprof_callgraph_list_traceables_for_symbol (SysprofCallgraph *self,
|
||||||
SysprofSymbol *symbol)
|
SysprofSymbol *symbol)
|
||||||
{
|
{
|
||||||
EggBitset *bitset;
|
SysprofCallgraphSummary *summary;
|
||||||
|
|
||||||
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL);
|
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL);
|
||||||
g_return_val_if_fail (SYSPROF_IS_SYMBOL (symbol), NULL);
|
g_return_val_if_fail (SYSPROF_IS_SYMBOL (symbol), NULL);
|
||||||
|
|
||||||
if ((bitset = g_hash_table_lookup (self->symbol_to_bitset, symbol)))
|
if ((summary = g_hash_table_lookup (self->symbol_to_summary, symbol)))
|
||||||
return _sysprof_document_bitset_index_new (self->traceables, bitset);
|
return _sysprof_document_bitset_index_new (self->traceables, summary->traceables);
|
||||||
|
|
||||||
return G_LIST_MODEL (g_list_store_new (SYSPROF_TYPE_DOCUMENT_TRACEABLE));
|
return G_LIST_MODEL (g_list_store_new (SYSPROF_TYPE_DOCUMENT_TRACEABLE));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user