[Lldb-commits] [lldb] Add symbol locator time for each module in statistics (PR #134563)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 22 19:41:41 PDT 2025
https://github.com/GeorgeHuyubo updated https://github.com/llvm/llvm-project/pull/134563
>From d266e0be70876752bf5b7f58a74a125950840cc3 Mon Sep 17 00:00:00 2001
From: George Hu <georgehuyubo at gmail.com>
Date: Tue, 22 Apr 2025 19:37:05 -0700
Subject: [PATCH] Add symbol locator time for each module in statistics
---
lldb/include/lldb/Core/Module.h | 6 +++++
lldb/include/lldb/Core/PluginManager.h | 7 +++--
lldb/include/lldb/Target/Statistics.h | 21 +++++++++++++++
lldb/source/Core/DynamicLoader.cpp | 11 ++++++--
lldb/source/Core/ModuleList.cpp | 8 +++---
lldb/source/Core/PluginManager.cpp | 27 ++++++++++++++-----
.../Platform/MacOSX/PlatformDarwinKernel.cpp | 4 +--
.../Process/MacOSX-Kernel/ProcessKDP.cpp | 11 +++++---
.../SymbolFile/DWARF/SymbolFileDWARF.cpp | 10 ++++---
.../SymbolVendor/ELF/SymbolVendorELF.cpp | 9 +++----
.../MacOSX/SymbolVendorMacOSX.cpp | 5 ++--
.../PECOFF/SymbolVendorPECOFF.cpp | 4 +--
.../SymbolVendor/wasm/SymbolVendorWasm.cpp | 4 +--
lldb/source/Target/Statistics.cpp | 18 +++++++++++++
14 files changed, 111 insertions(+), 34 deletions(-)
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 1ad67d6747850..8bb55c95773bc 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -885,6 +885,10 @@ class Module : public std::enable_shared_from_this<Module>,
/// ElapsedTime RAII object.
StatsDuration &GetSymtabIndexTime() { return m_symtab_index_time; }
+ StatisticsMap &GetSymbolLocatorStatistics() {
+ return m_symbol_locator_duration_map;
+ }
+
void ResetStatistics();
/// \class LookupInfo Module.h "lldb/Core/Module.h"
@@ -1064,6 +1068,8 @@ class Module : public std::enable_shared_from_this<Module>,
/// time for the symbol tables can be aggregated here.
StatsDuration m_symtab_index_time;
+ StatisticsMap m_symbol_locator_duration_map;
+
/// A set of hashes of all warnings and errors, to avoid reporting them
/// multiple times to the same Debugger.
llvm::DenseMap<llvm::stable_hash, std::unique_ptr<std::once_flag>>
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index a6dab045adf27..4f856b0d01a55 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -12,6 +12,7 @@
#include "lldb/Core/Architecture.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Statistics.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
@@ -377,11 +378,13 @@ class PluginManager {
static SymbolLocatorCreateInstance
GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx);
- static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec);
+ static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec,
+ StatisticsMap &map);
static FileSpec
LocateExecutableSymbolFile(const ModuleSpec &module_spec,
- const FileSpecList &default_search_paths);
+ const FileSpecList &default_search_paths,
+ StatisticsMap &map);
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
Status &error,
diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h
index b87a12a8ab9cd..63595c090efed 100644
--- a/lldb/include/lldb/Target/Statistics.h
+++ b/lldb/include/lldb/Target/Statistics.h
@@ -90,6 +90,26 @@ class ElapsedTime {
}
};
+/// A class to count time for plugins
+class StatisticsMap {
+public:
+ void add(llvm::StringRef key, double value) {
+ if (key.empty())
+ return;
+ auto it = map.find(key);
+ if (it == map.end())
+ map.try_emplace(key, value);
+ else
+ it->second += value;
+ }
+ void merge(StatisticsMap map_to_merge) {
+ for (const auto &entry : map_to_merge.map) {
+ add(entry.first(), entry.second);
+ }
+ }
+ llvm::StringMap<double> map;
+};
+
/// A class to count success/fail statistics.
struct StatsSuccessFail {
StatsSuccessFail(llvm::StringRef n) : name(n.str()) {}
@@ -118,6 +138,7 @@ struct ModuleStats {
// track down all of the stats that contribute to this module.
std::vector<intptr_t> symfile_modules;
llvm::StringMap<llvm::json::Value> type_system_stats;
+ StatisticsMap symbol_locator_time;
double symtab_parse_time = 0.0;
double symtab_index_time = 0.0;
uint32_t num_symbols_loaded = 0;
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index 76c71d2a49a48..291e6b73a2c39 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -243,15 +243,22 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
// find an executable and symbol file.
if (!module_sp) {
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
+ StatisticsMap symbol_locator_map;
module_spec.GetSymbolFileSpec() =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ PluginManager::LocateExecutableSymbolFile(module_spec, search_paths,
+ symbol_locator_map);
ModuleSpec objfile_module_spec =
- PluginManager::LocateExecutableObjectFile(module_spec);
+ PluginManager::LocateExecutableObjectFile(module_spec,
+ symbol_locator_map);
module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
module_sp = std::make_shared<Module>(module_spec);
}
+
+ if (module_sp) {
+ module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
+ }
}
// If we haven't found a binary, or we don't have a SymbolFile, see
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 2b8ccab2406c6..6052cc151744d 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -917,9 +917,10 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
// Fixup the incoming path in case the path points to a valid file, yet the
// arch or UUID (if one was passed in) don't match.
- ModuleSpec located_binary_modulespec =
- PluginManager::LocateExecutableObjectFile(module_spec);
-
+ ModuleSpec located_binary_modulespec;
+ StatisticsMap symbol_locator_map;
+ located_binary_modulespec = PluginManager::LocateExecutableObjectFile(
+ module_spec, symbol_locator_map);
// Don't look for the file if it appears to be the same one we already
// checked for above...
if (located_binary_modulespec.GetFileSpec() != module_file_spec) {
@@ -992,6 +993,7 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
// By getting the object file we can guarantee that the architecture
// matches
if (module_sp && module_sp->GetObjectFile()) {
+ module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
if (module_sp->GetObjectFile()->GetType() ==
ObjectFile::eTypeStubLibrary) {
module_sp.reset();
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index e6cb248ef31ce..7511592cfa4b6 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1217,12 +1217,18 @@ PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) {
}
ModuleSpec
-PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
+PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec,
+ StatisticsMap &map) {
auto instances = GetSymbolLocatorInstances().GetSnapshot();
for (auto &instance : instances) {
if (instance.locate_executable_object_file) {
- std::optional<ModuleSpec> result =
- instance.locate_executable_object_file(module_spec);
+ StatsDuration time;
+ std::optional<ModuleSpec> result;
+ {
+ ElapsedTime elapsed(time);
+ result = instance.locate_executable_object_file(module_spec);
+ }
+ map.add(instance.name, time.get().count());
if (result)
return *result;
}
@@ -1231,12 +1237,19 @@ PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
}
FileSpec PluginManager::LocateExecutableSymbolFile(
- const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
- auto instances = GetSymbolLocatorInstances().GetSnapshot();
+ const ModuleSpec &module_spec, const FileSpecList &default_search_paths,
+ StatisticsMap &map) {
+ auto instances = GetSymbolLocatorInstances().GetSnapshot();
for (auto &instance : instances) {
if (instance.locate_executable_symbol_file) {
- std::optional<FileSpec> result = instance.locate_executable_symbol_file(
- module_spec, default_search_paths);
+ StatsDuration time;
+ std::optional<FileSpec> result;
+ {
+ ElapsedTime elapsed(time);
+ result = instance.locate_executable_symbol_file(module_spec,
+ default_search_paths);
+ }
+ map.add(instance.name, time.get().count());
if (result)
return *result;
}
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
index 4fbead97e9c1a..54869001b7b81 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -814,8 +814,8 @@ Status PlatformDarwinKernel::GetSharedModuleKernel(
// append ".dSYM" to the filename for the SymbolFile.
FileSpecList search_paths =
process->GetTarget().GetDebugFileSearchPaths();
- FileSpec dsym_fspec =
- PluginManager::LocateExecutableSymbolFile(kern_spec, search_paths);
+ FileSpec dsym_fspec = PluginManager::LocateExecutableSymbolFile(
+ kern_spec, search_paths, module_sp->GetSymbolLocatorStatistics());
if (FileSystem::Instance().Exists(dsym_fspec))
module_sp->SetSymbolFileFileSpec(dsym_fspec);
if (did_create_ptr)
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 6cc01436aef20..60952958cc0d1 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -276,12 +276,15 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
// Lookup UUID locally, before attempting dsymForUUID like action
FileSpecList search_paths =
Target::GetDefaultDebugFileSearchPaths();
+
+ StatisticsMap symbol_locator_map;
module_spec.GetSymbolFileSpec() =
- PluginManager::LocateExecutableSymbolFile(module_spec,
- search_paths);
+ PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths, symbol_locator_map);
if (module_spec.GetSymbolFileSpec()) {
ModuleSpec executable_module_spec =
- PluginManager::LocateExecutableObjectFile(module_spec);
+ PluginManager::LocateExecutableObjectFile(
+ module_spec, symbol_locator_map);
if (FileSystem::Instance().Exists(
executable_module_spec.GetFileSpec())) {
module_spec.GetFileSpec() =
@@ -297,6 +300,8 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
ModuleSP module_sp(new Module(module_spec));
+ module_sp->GetSymbolLocatorStatistics().merge(
+ symbol_locator_map);
if (module_sp.get() && module_sp->GetObjectFile()) {
// Get the current target executable
ModuleSP exe_module_sp(target.GetExecutableModule());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index b95159d882bc7..60013248c4b2c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4255,8 +4255,9 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle());
LLDB_LOG(log, "Searching for DWP using: \"{0}\"",
module_spec.GetSymbolFileSpec());
- dwp_filespec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ dwp_filespec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths,
+ m_objfile_sp->GetModule()->GetSymbolLocatorStatistics());
if (FileSystem::Instance().Exists(dwp_filespec)) {
break;
}
@@ -4267,8 +4268,9 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
// find the correct DWP file, as the Debuginfod plugin uses *only* this
// data to correctly match the DWP file with the binary.
module_spec.GetUUID() = m_objfile_sp->GetUUID();
- dwp_filespec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ dwp_filespec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths,
+ m_objfile_sp->GetModule()->GetSymbolLocatorStatistics());
}
if (FileSystem::Instance().Exists(dwp_filespec)) {
LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec);
diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index a2c3825cd537f..380986d8afab7 100644
--- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -103,14 +103,14 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
module_spec.GetSymbolFileSpec() = fspec;
module_spec.GetUUID() = uuid;
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
- FileSpec dsym_fspec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ FileSpec dsym_fspec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths, module_sp->GetSymbolLocatorStatistics());
if (!dsym_fspec || IsDwpSymbolFile(module_sp, dsym_fspec)) {
// If we have a stripped binary or if we have a DWP file, SymbolLocator
// plugins may be able to give us an unstripped binary or an
// 'only-keep-debug' stripped file.
- ModuleSpec unstripped_spec =
- PluginManager::LocateExecutableObjectFile(module_spec);
+ ModuleSpec unstripped_spec = PluginManager::LocateExecutableObjectFile(
+ module_spec, module_sp->GetSymbolLocatorStatistics());
if (!unstripped_spec)
return nullptr;
// The default SymbolLocator plugin returns the original binary if no other
@@ -127,7 +127,6 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
dsym_file_data_sp, dsym_file_data_offset);
if (!dsym_objfile_sp)
return nullptr;
-
// This objfile is for debugging purposes. Sadly, ObjectFileELF won't
// be able to figure this out consistently as the symbol file may not
// have stripped the code sections, etc.
diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index f46bff8f7d12e..6a0b0ffee7e2d 100644
--- a/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -134,8 +134,9 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
ModuleSpec module_spec(file_spec, module_sp->GetArchitecture());
module_spec.GetUUID() = module_sp->GetUUID();
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
- dsym_fspec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+
+ dsym_fspec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths, module_sp->GetSymbolLocatorStatistics());
if (module_spec.GetSourceMappingList().GetSize())
module_sp->GetSourceMappingList().Append(
module_spec.GetSourceMappingList(), true);
diff --git a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
index 6393363db51f1..33fdadce07dee 100644
--- a/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp
@@ -85,8 +85,8 @@ SymbolVendorPECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
module_spec.GetSymbolFileSpec() = fspec;
module_spec.GetUUID() = uuid;
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
- FileSpec dsym_fspec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ FileSpec dsym_fspec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths, module_sp->GetSymbolLocatorStatistics());
if (!dsym_fspec)
return nullptr;
diff --git a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
index f8a9389c0ff93..c18af06fbdc98 100644
--- a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
+++ b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
@@ -85,8 +85,8 @@ SymbolVendorWasm::CreateInstance(const lldb::ModuleSP &module_sp,
module_spec.GetSymbolFileSpec() = *symbol_file_spec;
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
- FileSpec sym_fspec =
- PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+ FileSpec sym_fspec = PluginManager::LocateExecutableSymbolFile(
+ module_spec, search_paths, module_sp->GetSymbolLocatorStatistics());
if (!sym_fspec)
return nullptr;
diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp
index 2bb93dfffa5aa..16e0d5b657233 100644
--- a/lldb/source/Target/Statistics.cpp
+++ b/lldb/source/Target/Statistics.cpp
@@ -72,6 +72,14 @@ json::Value ModuleStats::ToJSON() const {
debug_info_had_incomplete_types);
module.try_emplace("symbolTableStripped", symtab_stripped);
module.try_emplace("symbolsLoaded", num_symbols_loaded);
+
+ if (!symbol_locator_time.map.empty()) {
+ json::Object obj;
+ for (const auto &entry : symbol_locator_time.map)
+ obj.try_emplace(entry.first().str(), entry.second);
+ module.try_emplace("symbolLocatorTime", std::move(obj));
+ }
+
if (!symfile_path.empty())
module.try_emplace("symbolFilePath", symfile_path);
@@ -289,6 +297,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(
json::Array json_targets;
json::Array json_modules;
+ StatisticsMap symbol_locator_total_time;
double symtab_parse_time = 0.0;
double symtab_index_time = 0.0;
double debug_parse_time = 0.0;
@@ -319,6 +328,8 @@ llvm::json::Value DebuggerStats::ReportStatistics(
ModuleStats module_stat;
module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
+ module_stat.symbol_locator_time = module->GetSymbolLocatorStatistics();
+ symbol_locator_total_time.merge(module_stat.symbol_locator_time);
Symtab *symtab = module->GetSymtab(/*can_create=*/false);
if (symtab) {
module_stat.num_symbols_loaded = symtab->GetNumSymbols();
@@ -427,6 +438,13 @@ llvm::json::Value DebuggerStats::ReportStatistics(
global_stats.try_emplace("targets", std::move(json_targets));
}
+ if (!symbol_locator_total_time.map.empty()) {
+ json::Object obj;
+ for (const auto &entry : symbol_locator_total_time.map)
+ obj.try_emplace(entry.first().str(), entry.second);
+ global_stats.try_emplace("totalSymbolLocatorTime", std::move(obj));
+ }
+
ConstStringStats const_string_stats;
json::Object json_memory{
{"strings", const_string_stats.ToJSON()},
More information about the lldb-commits
mailing list