libsysprof-analyze: make SysprofDocumentSymbols private

This instead moves to a public API on the document to symbolize now
that we've gotten much of the necessary bits private in loading the
document. This commit ensures that we only do loading via the loader
now (and removes the incorrect use from the tests so they too go
through the loader).

We check for NoSymbolizer in document symbols so that we can skip any
decoding. That keeps various use cases fast where you don't want to
waste time on symbolizing if you don't need to look at symbols.

There is plenty more we can do to batch decode symbols with some more
API changes, but that will come after we have kernel/userland decoding
integrated from this library.

We may still want to get all symbols into a single symbol cache, but
given that we have address ranges associated with them, that may not
be very useful beyond the hashtable to pid-specific cache we have now.

If symbols were shared between processes, that'd make more sense, but
we aren't doing that (albeit strings are shared between symbol
instances to reduce that overhead).
This commit is contained in:
Christian Hergert
2023-05-12 17:20:10 -07:00
parent ed030d2c25
commit 00ecc41209
18 changed files with 463 additions and 268 deletions

View File

@ -9,9 +9,10 @@ int
main (int argc,
char *argv[])
{
SysprofDocument *document;
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GError) error = NULL;
const char *filename;
GError *error = NULL;
guint n_items;
sysprof_clock_init ();
@ -24,7 +25,10 @@ main (int argc,
filename = argv[1];
if (!(document = _sysprof_document_new (filename, &error)))
loader = sysprof_document_loader_new (filename);
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
{
g_printerr ("Failed to load %s: %s\n",
filename, error->message);
@ -88,7 +92,5 @@ main (int argc,
g_printerr ("%u frames\n", n_items);
g_clear_object (&document);
return 0;
}

View File

@ -26,6 +26,7 @@ int
main (int argc,
char *argv[])
{
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GListModel) files = NULL;
g_autoptr(GError) error = NULL;
@ -37,7 +38,10 @@ main (int argc,
return 1;
}
if (!(document = _sysprof_document_new (argv[1], &error)))
loader = sysprof_document_loader_new (argv[1]);
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
{
g_printerr ("Failed to open capture: %s\n", error->message);
return 1;

View File

@ -26,6 +26,7 @@ int
main (int argc,
char *argv[])
{
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GListModel) processes = NULL;
g_autoptr(GError) error = NULL;
@ -37,7 +38,10 @@ main (int argc,
return 1;
}
if (!(document = _sysprof_document_new (argv[1], &error)))
loader = sysprof_document_loader_new (argv[1]);
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
{
g_printerr ("Failed to open capture: %s\n", error->message);
return 1;

View File

@ -26,6 +26,7 @@ int
main (int argc,
char *argv[])
{
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_autoptr(SysprofDocumentFile) file = NULL;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GListModel) files = NULL;
@ -38,7 +39,10 @@ main (int argc,
return 1;
}
if (!(document = _sysprof_document_new (argv[1], &error)))
loader = sysprof_document_loader_new (argv[1]);
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
{
g_printerr ("Failed to open capture: %s\n", error->message);
return 1;

View File

@ -7,63 +7,88 @@
static GMainLoop *main_loop;
static void
symbolize_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
load_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
SysprofDocument *document = (SysprofDocument *)object;
g_autoptr(SysprofDocumentSymbols) symbols = NULL;
SysprofDocumentLoader *loader = (SysprofDocumentLoader *)object;
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(GListModel) traceables = NULL;
g_autoptr(GError) error = NULL;
SysprofAddress addresses[128];
g_autoptr(GString) str = NULL;
SysprofSymbol *symbols[128];
guint n_symbols;
guint n_items;
g_assert (SYSPROF_IS_DOCUMENT (document));
g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader));
g_assert (G_IS_ASYNC_RESULT (result));
if (!(symbols = _sysprof_document_symbolize_finish (document, result, &error)))
g_error ("Failed to symbolize: %s", error->message);
if (!(document = sysprof_document_loader_load_finish (loader, result, &error)))
g_error ("Failed to load document: %s", error->message);
traceables = sysprof_document_list_traceables (document);
n_items = g_list_model_get_n_items (traceables);
str = g_string_new ("");
for (guint i = 0; i < n_items; i++)
{
g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (traceables, i);
SysprofAddressContext last_context;
guint depth;
int pid;
str->len = 0;
str->str[0] = 0;
g_assert (traceable != NULL);
g_assert (SYSPROF_IS_DOCUMENT_TRACEABLE (traceable));
last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable));
depth = sysprof_document_traceable_get_stack_addresses (traceable, addresses, G_N_ELEMENTS (addresses));
n_symbols = sysprof_document_symbolize_traceable (document,
traceable,
symbols,
G_N_ELEMENTS (symbols));
g_print ("%s depth=%u pid=%u\n",
G_OBJECT_TYPE_NAME (traceable), depth, pid);
G_OBJECT_TYPE_NAME (traceable),
n_symbols,
sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable)));
for (guint j = 0; j < depth; j++)
for (guint j = 0; j < n_symbols; j++)
{
SysprofAddress address = addresses[j];
SysprofSymbol *symbol = sysprof_document_symbols_lookup (symbols, pid, last_context, address);
SysprofAddressContext context;
if (sysprof_address_is_context_switch (address, &context))
last_context = context;
SysprofSymbol *symbol = symbols[j];
const char *name;
const char *path;
const char *nick;
if (symbol != NULL)
g_print (" %02d: %p: %s [%s]\n",
j,
GSIZE_TO_POINTER (address),
sysprof_symbol_get_name (symbol),
sysprof_symbol_get_binary_path (symbol) ?: "<unresolved>");
{
name = sysprof_symbol_get_name (symbol);
path = sysprof_symbol_get_binary_path (symbol);
nick = sysprof_symbol_get_binary_nick (symbol);
}
else
g_print (" %02d: %p:\n", j, GSIZE_TO_POINTER (address));
{
name = path = nick = NULL;
}
g_string_append_printf (str,
" %02d: 0x%"G_GINT64_MODIFIER"x:",
j,
sysprof_document_traceable_get_stack_address (traceable, j));
if (name)
g_string_append_printf (str, " %s", name);
if (path)
g_string_append_printf (str, " [%s]", path);
if (nick)
g_string_append_printf (str, " (%s)", nick);
g_string_append_c (str, '\n');
}
g_print (" ================\n");
g_string_append (str, " ================\n");
write (STDOUT_FILENO, str->str, str->len);
}
g_print ("Document symbolized\n");
@ -75,10 +100,8 @@ int
main (int argc,
char *argv[])
{
g_autoptr(SysprofDocument) document = NULL;
g_autoptr(SysprofMultiSymbolizer) multi = NULL;
g_autoptr(SysprofDocumentLoader) loader = NULL;
g_autoptr(GError) error = NULL;
const char *filename;
main_loop = g_main_loop_new (NULL, FALSE);
@ -88,23 +111,8 @@ main (int argc,
return 1;
}
filename = argv[1];
if (!(document = _sysprof_document_new (filename, &error)))
{
g_printerr ("Failed to load document: %s\n", error->message);
return 1;
}
multi = sysprof_multi_symbolizer_new ();
sysprof_multi_symbolizer_add (multi, sysprof_bundled_symbolizer_new ());
_sysprof_document_symbolize_async (document,
SYSPROF_SYMBOLIZER (multi),
NULL,
symbolize_cb,
NULL);
loader = sysprof_document_loader_new (argv[1]);
sysprof_document_loader_load_async (loader, NULL, load_cb, NULL);
g_main_loop_run (main_loop);
return 0;