LLDB mainline
Statistics.cpp
Go to the documentation of this file.
1//===-- Statistics.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/Module.h"
14#include "lldb/Target/Process.h"
15#include "lldb/Target/Target.h"
17
18using namespace lldb;
19using namespace lldb_private;
20using namespace llvm;
21
22static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
23 const std::string &str) {
24 if (str.empty())
25 return;
26 if (LLVM_LIKELY(llvm::json::isUTF8(str)))
27 obj.try_emplace(key, str);
28 else
29 obj.try_emplace(key, llvm::json::fixUTF8(str));
30}
31
32json::Value StatsSuccessFail::ToJSON() const {
33 return json::Object{{"successes", successes}, {"failures", failures}};
34}
35
36static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
38 end.time_since_epoch() - start.time_since_epoch();
39 return elapsed.count();
40}
41
44 for (ModuleSP module_sp : target.GetImages().Modules())
45 m_module_identifiers.emplace_back((intptr_t)module_sp.get());
46}
47
48json::Value ModuleStats::ToJSON() const {
49 json::Object module;
50 EmplaceSafeString(module, "path", path);
51 EmplaceSafeString(module, "uuid", uuid);
52 EmplaceSafeString(module, "triple", triple);
53 module.try_emplace("identifier", identifier);
54 module.try_emplace("symbolTableParseTime", symtab_parse_time);
55 module.try_emplace("symbolTableIndexTime", symtab_index_time);
56 module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
57 module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
58 module.try_emplace("debugInfoParseTime", debug_parse_time);
59 module.try_emplace("debugInfoIndexTime", debug_index_time);
60 module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
61 module.try_emplace("debugInfoIndexLoadedFromCache",
63 module.try_emplace("debugInfoIndexSavedToCache",
65 module.try_emplace("debugInfoEnabled", debug_info_enabled);
66 module.try_emplace("debugInfoHadVariableErrors",
68 module.try_emplace("debugInfoHadIncompleteTypes",
70 module.try_emplace("symbolTableStripped", symtab_stripped);
71 if (!symfile_path.empty())
72 module.try_emplace("symbolFilePath", symfile_path);
73
74 if (!symfile_modules.empty()) {
75 json::Array symfile_ids;
76 for (const auto symfile_id: symfile_modules)
77 symfile_ids.emplace_back(symfile_id);
78 module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
79 }
80
81 if (!type_system_stats.empty()) {
82 json::Array type_systems;
83 for (const auto &entry : type_system_stats) {
84 json::Object obj;
85 obj.try_emplace(entry.first().str(), entry.second);
86 type_systems.emplace_back(std::move(obj));
87 }
88 module.try_emplace("typeSystemInfo", std::move(type_systems));
89 }
90
91 return module;
92}
93
94llvm::json::Value ConstStringStats::ToJSON() const {
95 json::Object obj;
96 obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
97 obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
98 obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
99 return obj;
100}
101
102json::Value TargetStats::ToJSON(Target &target) {
103 CollectStats(target);
104
105 json::Array json_module_uuid_array;
106 for (auto module_identifier : m_module_identifiers)
107 json_module_uuid_array.emplace_back(module_identifier);
108
109 json::Object target_metrics_json{
112 {"moduleIdentifiers", std::move(json_module_uuid_array)}};
113
115 double elapsed_time =
117 target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
118 }
120 double elapsed_time =
122 target_metrics_json.try_emplace("firstStopTime", elapsed_time);
123 }
124 target_metrics_json.try_emplace("targetCreateTime",
125 m_create_time.get().count());
126
127 json::Array breakpoints_array;
128 double totalBreakpointResolveTime = 0.0;
129 // Rport both the normal breakpoint list and the internal breakpoint list.
130 for (int i = 0; i < 2; ++i) {
131 BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
132 std::unique_lock<std::recursive_mutex> lock;
133 breakpoints.GetListMutex(lock);
134 size_t num_breakpoints = breakpoints.GetSize();
135 for (size_t i = 0; i < num_breakpoints; i++) {
136 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
137 breakpoints_array.push_back(bp->GetStatistics());
138 totalBreakpointResolveTime += bp->GetResolveTime().count();
139 }
140 }
141
142 ProcessSP process_sp = target.GetProcessSP();
143 if (process_sp) {
144 UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
145 if (unix_signals_sp)
146 target_metrics_json.try_emplace("signals",
147 unix_signals_sp->GetHitCountStatistics());
148 uint32_t stop_id = process_sp->GetStopID();
149 target_metrics_json.try_emplace("stopCount", stop_id);
150 }
151 target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array));
152 target_metrics_json.try_emplace("totalBreakpointResolveTime",
153 totalBreakpointResolveTime);
154 target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count);
155
156 return target_metrics_json;
157}
158
160 m_launch_or_attach_time = StatsClock::now();
161 m_first_private_stop_time = std::nullopt;
162}
163
165 // Launching and attaching has many paths depending on if synchronous mode
166 // was used or if we are stopping at the entry point or not. Only set the
167 // first stop time if it hasn't already been set.
169 m_first_private_stop_time = StatsClock::now();
170}
171
173 // Launching and attaching has many paths depending on if synchronous mode
174 // was used or if we are stopping at the entry point or not. Only set the
175 // first stop time if it hasn't already been set.
177 m_first_public_stop_time = StatsClock::now();
178}
179
182}
183
185
186llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
187 Target *target) {
188 json::Array json_targets;
189 json::Array json_modules;
190 double symtab_parse_time = 0.0;
191 double symtab_index_time = 0.0;
192 double debug_parse_time = 0.0;
193 double debug_index_time = 0.0;
194 uint32_t symtabs_loaded = 0;
195 uint32_t symtabs_saved = 0;
196 uint32_t debug_index_loaded = 0;
197 uint32_t debug_index_saved = 0;
198 uint64_t debug_info_size = 0;
199 if (target) {
200 json_targets.emplace_back(target->ReportStatistics());
201 } else {
202 for (const auto &target : debugger.GetTargetList().Targets())
203 json_targets.emplace_back(target->ReportStatistics());
204 }
205 std::vector<ModuleStats> modules;
206 std::lock_guard<std::recursive_mutex> guard(
208 const uint64_t num_modules = Module::GetNumberAllocatedModules();
209 uint32_t num_debug_info_enabled_modules = 0;
210 uint32_t num_modules_has_debug_info = 0;
211 uint32_t num_modules_with_variable_errors = 0;
212 uint32_t num_modules_with_incomplete_types = 0;
213 uint32_t num_stripped_modules = 0;
214 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
215 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
216 ModuleStats module_stat;
217 module_stat.identifier = (intptr_t)module;
218 module_stat.path = module->GetFileSpec().GetPath();
219 if (ConstString object_name = module->GetObjectName()) {
220 module_stat.path.append(1, '(');
221 module_stat.path.append(object_name.GetStringRef().str());
222 module_stat.path.append(1, ')');
223 }
224 module_stat.uuid = module->GetUUID().GetAsString();
225 module_stat.triple = module->GetArchitecture().GetTriple().str();
226 module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
227 module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
228 Symtab *symtab = module->GetSymtab();
229 if (symtab) {
230 module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
231 if (module_stat.symtab_loaded_from_cache)
232 ++symtabs_loaded;
233 module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
234 if (module_stat.symtab_saved_to_cache)
235 ++symtabs_saved;
236 }
237 SymbolFile *sym_file = module->GetSymbolFile();
238 if (sym_file) {
239
240 if (sym_file->GetObjectFile() != module->GetObjectFile())
241 module_stat.symfile_path =
242 sym_file->GetObjectFile()->GetFileSpec().GetPath();
243 module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
244 module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
245 module_stat.debug_info_size = sym_file->GetDebugInfoSize();
249 ++debug_index_loaded;
252 if (module_stat.debug_info_index_saved_to_cache)
253 ++debug_index_saved;
254 ModuleList symbol_modules = sym_file->GetDebugInfoModules();
255 for (const auto &symbol_module: symbol_modules.Modules())
256 module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
257 module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
258 if (module_stat.symtab_stripped)
259 ++num_stripped_modules;
260 module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
261 module_stat.debug_info_size > 0;
264 if (module_stat.debug_info_enabled)
265 ++num_debug_info_enabled_modules;
266 if (module_stat.debug_info_size > 0)
267 ++num_modules_has_debug_info;
268 if (module_stat.debug_info_had_variable_errors)
269 ++num_modules_with_variable_errors;
270 }
271 symtab_parse_time += module_stat.symtab_parse_time;
272 symtab_index_time += module_stat.symtab_index_time;
273 debug_parse_time += module_stat.debug_parse_time;
274 debug_index_time += module_stat.debug_index_time;
275 debug_info_size += module_stat.debug_info_size;
276 module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
277 if (auto stats = ts->ReportStatistics())
278 module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
279 if (ts->GetHasForcefullyCompletedTypes())
280 module_stat.debug_info_had_incomplete_types = true;
281 return true;
282 });
283 if (module_stat.debug_info_had_incomplete_types)
284 ++num_modules_with_incomplete_types;
285
286 json_modules.emplace_back(module_stat.ToJSON());
287 }
288
289 ConstStringStats const_string_stats;
290 json::Object json_memory{
291 {"strings", const_string_stats.ToJSON()},
292 };
293
294 json::Object global_stats{
295 {"targets", std::move(json_targets)},
296 {"modules", std::move(json_modules)},
297 {"memory", std::move(json_memory)},
298 {"totalSymbolTableParseTime", symtab_parse_time},
299 {"totalSymbolTableIndexTime", symtab_index_time},
300 {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
301 {"totalSymbolTablesSavedToCache", symtabs_saved},
302 {"totalDebugInfoParseTime", debug_parse_time},
303 {"totalDebugInfoIndexTime", debug_index_time},
304 {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
305 {"totalDebugInfoIndexSavedToCache", debug_index_saved},
306 {"totalDebugInfoByteSize", debug_info_size},
307 {"totalModuleCount", num_modules},
308 {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
309 {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
310 {"totalModuleCountWithIncompleteTypes", num_modules_with_incomplete_types},
311 {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
312 {"totalSymbolTableStripped", num_stripped_modules},
313 };
314 return std::move(global_stats);
315}
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:36
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, const std::string &str)
Definition: Statistics.cpp:22
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
General Outline: Allows adding and removing breakpoints and find by ID and index.
void GetListMutex(std::unique_lock< std::recursive_mutex > &lock)
Sets the passed in Locker to hold the Breakpoint List mutex.
size_t GetSize() const
Returns the number of elements in this breakpoint list.
lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const
Returns a shared pointer to the breakpoint with index i.
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:81
llvm::json::Value GetStatistics()
Get statistics associated with this breakpoint in JSON format.
StatsDuration::Duration GetResolveTime() const
Get the time it took to resolve all locations in this breakpoint.
Definition: Breakpoint.h:593
A uniqued constant string class.
Definition: ConstString.h:40
static bool g_collecting_stats
Definition: Statistics.h:183
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target)
Get metrics associated with one or all targets in a debugger in JSON format.
Definition: Statistics.cpp:186
A class to manage flag bits.
Definition: Debugger.h:79
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:205
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
A collection class for Module objects.
Definition: ModuleList.h:82
ModuleIterable Modules() const
Definition: ModuleList.h:510
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:88
const lldb_private::UUID & GetUUID()
Get a reference to the UUID value contained in this object.
Definition: Module.cpp:340
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
Definition: Module.cpp:1255
virtual SymbolFile * GetSymbolFile(bool can_create=true, Stream *feedback_strm=nullptr)
Get the module's symbol file.
Definition: Module.cpp:1065
ConstString GetObjectName() const
Definition: Module.cpp:1253
static Module * GetAllocatedModuleAtIndex(size_t idx)
Definition: Module.cpp:124
static std::recursive_mutex & GetAllocationModuleCollectionMutex()
Definition: Module.cpp:106
Symtab * GetSymtab()
Definition: Module.cpp:1091
static size_t GetNumberAllocatedModules()
Definition: Module.cpp:118
void ForEachTypeSystem(llvm::function_ref< bool(lldb::TypeSystemSP)> callback)
Call callback for each TypeSystem in this Module.
Definition: Module.cpp:370
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1106
StatsDuration & GetSymtabIndexTime()
Accessor for the symbol table index time metric.
Definition: Module.h:926
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:497
StatsDuration & GetSymtabParseTime()
Accessor for the symbol table parse time metric.
Definition: Module.h:920
virtual bool IsStripped()=0
Detect if this object file has been stripped of local symbols.
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
Definition: ObjectFile.h:274
Duration get() const
Definition: Statistics.h:33
std::chrono::duration< double > Duration
Definition: Statistics.h:31
Provides public interface for all SymbolFiles.
Definition: SymbolFile.h:49
virtual bool GetDebugInfoIndexWasLoadedFromCache() const =0
Accessors for the bool that indicates if the debug info index was loaded from, or saved to the module...
virtual bool GetDebugInfoIndexWasSavedToCache() const =0
virtual StatsDuration::Duration GetDebugInfoParseTime()
Return the time taken to parse the debug information.
Definition: SymbolFile.h:398
virtual bool GetLoadDebugInfoEnabled()
Whether debug info will be loaded or not.
Definition: SymbolFile.h:134
virtual bool GetDebugInfoHadFrameVariableErrors() const =0
Accessors for the bool that indicates if there was debug info, but errors stopped variables from bein...
virtual uint64_t GetDebugInfoSize()=0
Metrics gathering functions.
virtual ModuleList GetDebugInfoModules()
Get the additional modules that this symbol file uses to parse debug info.
Definition: SymbolFile.h:414
virtual StatsDuration::Duration GetDebugInfoIndexTime()
Return the time it took to index the debug information in the object file.
Definition: SymbolFile.h:405
virtual ObjectFile * GetObjectFile()=0
bool GetWasLoadedFromCache() const
Accessors for the bool that indicates if the debug info index was loaded from, or saved to the module...
Definition: Symtab.h:228
bool GetWasSavedToCache() const
Definition: Symtab.h:234
TargetIterable Targets()
Definition: TargetList.h:194
llvm::json::Value ToJSON(Target &target)
Definition: Statistics.cpp:102
StatsSuccessFail m_frame_var
Definition: Statistics.h:153
std::optional< StatsTimepoint > m_launch_or_attach_time
Definition: Statistics.h:149
uint32_t m_source_map_deduce_count
Definition: Statistics.h:155
void CollectStats(Target &target)
Definition: Statistics.cpp:42
StatsDuration m_create_time
Definition: Statistics.h:148
std::optional< StatsTimepoint > m_first_public_stop_time
Definition: Statistics.h:151
StatsSuccessFail m_expr_eval
Definition: Statistics.h:152
std::vector< intptr_t > m_module_identifiers
Definition: Statistics.h:154
std::optional< StatsTimepoint > m_first_private_stop_time
Definition: Statistics.h:150
BreakpointList & GetBreakpointList(bool internal=false)
Definition: Target.cpp:313
const lldb::ProcessSP & GetProcessSP() const
Definition: Target.cpp:220
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:967
llvm::json::Value ReportStatistics()
Get metrics associated with this target in JSON format.
Definition: Target.cpp:4916
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:49
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::chrono::time_point< StatsClock > StatsTimepoint
Definition: Statistics.h:27
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::TypeSystem > TypeSystemSP
Definition: lldb-forward.h:444
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
Definition: lldb-forward.h:454
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:368
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:354
Definition: Debugger.h:53
ConstString::MemoryStats stats
Definition: Statistics.h:130
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:94
A class that represents statistics for a since lldb_private::Module.
Definition: Statistics.h:99
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:48
llvm::StringMap< llvm::json::Value > type_system_stats
Definition: Statistics.h:112
std::vector< intptr_t > symfile_modules
Definition: Statistics.h:111
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:32