From d4bc913607ad0c2e24af44c1dbca2005da496026 Mon Sep 17 00:00:00 2001 From: Jeremy <51220084+jeremy-rifkin@users.noreply.github.com> Date: Sat, 30 Sep 2023 03:37:16 -0400 Subject: [PATCH] Setup global dwarf_resolver cache for dwarf resolving --- src/symbols/symbols_with_libdwarf.cpp | 53 +++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/symbols/symbols_with_libdwarf.cpp b/src/symbols/symbols_with_libdwarf.cpp index 3c0e049..966aa81 100644 --- a/src/symbols/symbols_with_libdwarf.cpp +++ b/src/symbols/symbols_with_libdwarf.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -199,6 +200,39 @@ namespace libdwarf { } } + dwarf_resolver(const dwarf_resolver&) = delete; + dwarf_resolver& operator=(const dwarf_resolver&) = delete; + + dwarf_resolver(dwarf_resolver&& other) : + obj_path(std::move(other.obj_path)), + dbg(other.dbg), + ok(other.ok), + aranges(other.aranges), + arange_count(other.arange_count), + line_contexts(std::move(other.line_contexts)), + subprograms_cache(std::move(other.subprograms_cache)), + cu_cache(std::move(other.cu_cache)), + tmp_object_path(std::move(other.tmp_object_path)) + { + other.dbg = nullptr; + other.aranges = nullptr; + } + + dwarf_resolver& operator=(dwarf_resolver&& other) { + obj_path = std::move(other.obj_path); + dbg = other.dbg; + ok = other.ok; + aranges = other.aranges; + arange_count = other.arange_count; + line_contexts = std::move(other.line_contexts); + subprograms_cache = std::move(other.subprograms_cache); + cu_cache = std::move(other.cu_cache); + tmp_object_path = std::move(other.tmp_object_path); + other.dbg = nullptr; + other.aranges = nullptr; + return *this; + } + // walk all CU's in a dbg, callback is called on each die and should return true to // continue traversal void walk_compilation_units(std::function fn) { @@ -633,19 +667,29 @@ namespace libdwarf { std::vector resolve_frames(const std::vector& frames) { std::vector trace(frames.size(), null_frame); static std::mutex mutex; + // cache resolvers since objects are likely to be traced more than once + static std::unordered_map resolver_map; // Locking around all libdwarf interaction per https://github.com/davea42/libdwarf-code/discussions/184 const std::lock_guard lock(mutex); for(const auto& obj_entry : collate_frames(frames, trace)) { try { const auto& obj_name = obj_entry.first; - dwarf_resolver resolver(obj_name); + optional resolver_object;// = nullopt; + dwarf_resolver* resolver = nullptr; + auto it = resolver_map.find(obj_name); + if(it != resolver_map.end()) { + resolver = &it->second; + } else { + resolver_object = dwarf_resolver(obj_name); + resolver = &resolver_object.unwrap(); + } // If there's no debug information it'll mark itself as not ok - if(resolver.ok) { + if(resolver->ok) { for(const auto& entry : obj_entry.second) { try { const auto& dlframe = entry.first.get(); auto& frame = entry.second.get(); - frame = resolver.resolve_frame(dlframe); + frame = resolver->resolve_frame(dlframe); } catch(...) { if(!should_absorb_trace_exceptions()) { throw; @@ -653,6 +697,9 @@ namespace libdwarf { } } } + if(resolver_object.has_value() && get_cache_mode() == cache_mode::prioritize_speed) { + resolver_map.insert({obj_name, std::move(resolver_object).unwrap()}); + } } catch(...) { if(!should_absorb_trace_exceptions()) { throw;