mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
gstinfo: Improve usage of libdw for backtraces
When getting backtraces, we were always creating a new Dwfl context and then discarding it. The problem with that is that it resulted in having to re-scan a lot of information for every single backtrace. In order to fix that issue, use a global on-demand Dwfl context and use it with a lock. Furthermore, we were scanning the mappings of the process (dwfl_linux_proc_report) for *every single step* in the backtrace, and that function is horrendously expensive (does sscanf on /proc/PID/maps ...). While there is a possibility that new mappings might be available (new plugins being loaded for example), we can limit ourselves to just do it once per backtrace. These two modifications speed up the elements_leaks unit test (which traces all pads with full backtraces) by a factor of 6. Partially fixes #567 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/504>
This commit is contained in:
parent
df52bdc5d4
commit
8c08cdf9fe
1 changed files with 37 additions and 13 deletions
|
@ -147,6 +147,28 @@ static char *gst_info_printf_pointer_extension_func (const char *format,
|
|||
|
||||
#ifdef HAVE_DW
|
||||
#include <elfutils/libdwfl.h>
|
||||
static Dwfl *_global_dwfl = NULL;
|
||||
static GMutex _dwfl_mutex;
|
||||
|
||||
#define GST_DWFL_LOCK() g_mutex_lock(&_dwfl_mutex);
|
||||
#define GST_DWFL_UNLOCK() g_mutex_unlock(&_dwfl_mutex);
|
||||
|
||||
static Dwfl *
|
||||
get_global_dwfl (void)
|
||||
{
|
||||
if (g_once_init_enter (&_global_dwfl)) {
|
||||
static Dwfl_Callbacks callbacks = {
|
||||
.find_elf = dwfl_linux_proc_find_elf,
|
||||
.find_debuginfo = dwfl_standard_find_debuginfo,
|
||||
};
|
||||
Dwfl *_dwfl = dwfl_begin (&callbacks);
|
||||
g_mutex_init (&_dwfl_mutex);
|
||||
g_once_init_leave (&_global_dwfl, _dwfl);
|
||||
}
|
||||
|
||||
return _global_dwfl;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DW */
|
||||
#endif /* HAVE_UNWIND */
|
||||
|
||||
|
@ -2800,12 +2822,6 @@ append_debug_info (GString * trace, Dwfl * dwfl, const void *ip)
|
|||
Dwfl_Module *module;
|
||||
const gchar *function_name;
|
||||
|
||||
if (dwfl_linux_proc_report (dwfl, getpid ()) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (dwfl_report_end (dwfl, NULL, NULL))
|
||||
return FALSE;
|
||||
|
||||
addr = (uintptr_t) ip;
|
||||
module = dwfl_addrmodule (dwfl, addr);
|
||||
function_name = dwfl_module_addrname (module, addr);
|
||||
|
@ -2843,13 +2859,15 @@ generate_unwind_trace (GstStackTraceFlags flags)
|
|||
|
||||
#ifdef HAVE_DW
|
||||
Dwfl *dwfl = NULL;
|
||||
Dwfl_Callbacks callbacks = {
|
||||
.find_elf = dwfl_linux_proc_find_elf,
|
||||
.find_debuginfo = dwfl_standard_find_debuginfo,
|
||||
};
|
||||
|
||||
if ((flags & GST_STACK_TRACE_SHOW_FULL))
|
||||
dwfl = dwfl_begin (&callbacks);
|
||||
if ((flags & GST_STACK_TRACE_SHOW_FULL)) {
|
||||
dwfl = get_global_dwfl ();
|
||||
if (G_UNLIKELY (dwfl == NULL)) {
|
||||
GST_WARNING ("Failed to initialize dwlf");
|
||||
goto done;
|
||||
}
|
||||
GST_DWFL_LOCK ();
|
||||
}
|
||||
#endif /* HAVE_DW */
|
||||
|
||||
unret = unw_getcontext (&uc);
|
||||
|
@ -2864,6 +2882,12 @@ generate_unwind_trace (GstStackTraceFlags flags)
|
|||
|
||||
goto done;
|
||||
}
|
||||
#ifdef HAVE_DW
|
||||
/* Due to plugins being loaded, mapping of process might have changed,
|
||||
* so always scan it. */
|
||||
if (dwfl_linux_proc_report (dwfl, getpid ()) != 0)
|
||||
goto done;
|
||||
#endif
|
||||
|
||||
while (unw_step (&cursor) > 0) {
|
||||
#ifdef HAVE_DW
|
||||
|
@ -2897,7 +2921,7 @@ generate_unwind_trace (GstStackTraceFlags flags)
|
|||
done:
|
||||
#ifdef HAVE_DW
|
||||
if (dwfl)
|
||||
dwfl_end (dwfl);
|
||||
GST_DWFL_UNLOCK ();
|
||||
#endif
|
||||
|
||||
return g_string_free (trace, FALSE);
|
||||
|
|
Loading…
Reference in a new issue