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"
16#include "lldb/Target/Process.h"
17#include "lldb/Target/Target.h"
19
20using namespace lldb;
21using namespace lldb_private;
22using namespace llvm;
23
24static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
25 const std::string &str) {
26 if (str.empty())
27 return;
28 if (LLVM_LIKELY(llvm::json::isUTF8(str)))
29 obj.try_emplace(key, str);
30 else
31 obj.try_emplace(key, llvm::json::fixUTF8(str));
32}
33
34json::Value StatsSuccessFail::ToJSON() const {
35 return json::Object{{"successes", successes}, {"failures", failures}};
36}
37
38static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
40 end.time_since_epoch() - start.time_since_epoch();
41 return elapsed.count();
42}
43
46 for (ModuleSP module_sp : target.GetImages().Modules())
47 m_module_identifiers.emplace_back((intptr_t)module_sp.get());
48}
49
50json::Value ModuleStats::ToJSON() const {
51 json::Object module;
52 EmplaceSafeString(module, "path", path);
53 EmplaceSafeString(module, "uuid", uuid);
54 EmplaceSafeString(module, "triple", triple);
55 module.try_emplace("identifier", identifier);
56 module.try_emplace("symbolTableParseTime", symtab_parse_time);
57 module.try_emplace("symbolTableIndexTime", symtab_index_time);
58 module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
59 module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
60 module.try_emplace("debugInfoParseTime", debug_parse_time);
61 module.try_emplace("debugInfoIndexTime", debug_index_time);
62 module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
63 module.try_emplace("debugInfoIndexLoadedFromCache",
65 module.try_emplace("debugInfoIndexSavedToCache",
67 module.try_emplace("debugInfoEnabled", debug_info_enabled);
68 module.try_emplace("debugInfoHadVariableErrors",
70 module.try_emplace("debugInfoHadIncompleteTypes",
72 module.try_emplace("symbolTableStripped", symtab_stripped);
73 if (!symfile_path.empty())
74 module.try_emplace("symbolFilePath", symfile_path);
75
76 if (!symfile_modules.empty()) {
77 json::Array symfile_ids;
78 for (const auto symfile_id: symfile_modules)
79 symfile_ids.emplace_back(symfile_id);
80 module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
81 }
82
83 if (!type_system_stats.empty()) {
84 json::Array type_systems;
85 for (const auto &entry : type_system_stats) {
86 json::Object obj;
87 obj.try_emplace(entry.first().str(), entry.second);
88 type_systems.emplace_back(std::move(obj));
89 }
90 module.try_emplace("typeSystemInfo", std::move(type_systems));
91 }
92
93 return module;
94}
95
96llvm::json::Value ConstStringStats::ToJSON() const {
97 json::Object obj;
98 obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
99 obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
100 obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
101 return obj;
102}
103
104json::Value
106 const lldb_private::StatisticsOptions &options) {
107 json::Object target_metrics_json;
108 ProcessSP process_sp = target.GetProcessSP();
109 const bool summary_only = options.summary_only;
110 if (!summary_only) {
111 CollectStats(target);
112
113 json::Array json_module_uuid_array;
114 for (auto module_identifier : m_module_identifiers)
115 json_module_uuid_array.emplace_back(module_identifier);
116
117 target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
118 target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
119 target_metrics_json.try_emplace("moduleIdentifiers",
120 std::move(json_module_uuid_array));
121
123 double elapsed_time =
125 target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
126 }
128 double elapsed_time =
130 target_metrics_json.try_emplace("firstStopTime", elapsed_time);
131 }
132 target_metrics_json.try_emplace("targetCreateTime",
133 m_create_time.get().count());
134
135 json::Array breakpoints_array;
136 double totalBreakpointResolveTime = 0.0;
137 // Report both the normal breakpoint list and the internal breakpoint list.
138 for (int i = 0; i < 2; ++i) {
139 BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
140 std::unique_lock<std::recursive_mutex> lock;
141 breakpoints.GetListMutex(lock);
142 size_t num_breakpoints = breakpoints.GetSize();
143 for (size_t i = 0; i < num_breakpoints; i++) {
144 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
145 breakpoints_array.push_back(bp->GetStatistics());
146 totalBreakpointResolveTime += bp->GetResolveTime().count();
147 }
148 }
149 target_metrics_json.try_emplace("breakpoints",
150 std::move(breakpoints_array));
151 target_metrics_json.try_emplace("totalBreakpointResolveTime",
152 totalBreakpointResolveTime);
153
154 if (process_sp) {
155 UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
156 if (unix_signals_sp)
157 target_metrics_json.try_emplace(
158 "signals", unix_signals_sp->GetHitCountStatistics());
159 }
160 }
161
162 // Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
163 // "shared-library-event".
164 {
165 uint32_t shared_library_event_breakpoint_hit_count = 0;
166 // The "shared-library-event" is only found in the internal breakpoint list.
167 BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
168 std::unique_lock<std::recursive_mutex> lock;
169 breakpoints.GetListMutex(lock);
170 size_t num_breakpoints = breakpoints.GetSize();
171 for (size_t i = 0; i < num_breakpoints; i++) {
172 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
173 if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
174 shared_library_event_breakpoint_hit_count += bp->GetHitCount();
175 }
176
177 target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
178 shared_library_event_breakpoint_hit_count);
179 }
180
181 if (process_sp) {
182 uint32_t stop_id = process_sp->GetStopID();
183 target_metrics_json.try_emplace("stopCount", stop_id);
184
185 llvm::StringRef dyld_plugin_name;
186 if (process_sp->GetDynamicLoader())
187 dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
188 target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
189 }
190 target_metrics_json.try_emplace("sourceMapDeduceCount",
192 return target_metrics_json;
193}
194
196 m_launch_or_attach_time = StatsClock::now();
197 m_first_private_stop_time = std::nullopt;
198}
199
201 // Launching and attaching has many paths depending on if synchronous mode
202 // was used or if we are stopping at the entry point or not. Only set the
203 // first stop time if it hasn't already been set.
205 m_first_private_stop_time = StatsClock::now();
206}
207
209 // Launching and attaching has many paths depending on if synchronous mode
210 // was used or if we are stopping at the entry point or not. Only set the
211 // first stop time if it hasn't already been set.
213 m_first_public_stop_time = StatsClock::now();
214}
215
218}
219
221
223 Debugger &debugger, Target *target,
224 const lldb_private::StatisticsOptions &options) {
225
226 const bool summary_only = options.summary_only;
227 const bool load_all_debug_info = options.load_all_debug_info;
228
229 json::Array json_targets;
230 json::Array json_modules;
231 double symtab_parse_time = 0.0;
232 double symtab_index_time = 0.0;
233 double debug_parse_time = 0.0;
234 double debug_index_time = 0.0;
235 uint32_t symtabs_loaded = 0;
236 uint32_t symtabs_saved = 0;
237 uint32_t debug_index_loaded = 0;
238 uint32_t debug_index_saved = 0;
239 uint64_t debug_info_size = 0;
240
241 std::vector<ModuleStats> modules;
242 std::lock_guard<std::recursive_mutex> guard(
244 const uint64_t num_modules = Module::GetNumberAllocatedModules();
245 uint32_t num_debug_info_enabled_modules = 0;
246 uint32_t num_modules_has_debug_info = 0;
247 uint32_t num_modules_with_variable_errors = 0;
248 uint32_t num_modules_with_incomplete_types = 0;
249 uint32_t num_stripped_modules = 0;
250 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
251 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
252 ModuleStats module_stat;
253 module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
254 module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
255 Symtab *symtab = module->GetSymtab();
256 if (symtab) {
257 module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
258 if (module_stat.symtab_loaded_from_cache)
259 ++symtabs_loaded;
260 module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
261 if (module_stat.symtab_saved_to_cache)
262 ++symtabs_saved;
263 }
264 SymbolFile *sym_file = module->GetSymbolFile();
265 if (sym_file) {
266 if (!summary_only) {
267 if (sym_file->GetObjectFile() != module->GetObjectFile())
268 module_stat.symfile_path =
269 sym_file->GetObjectFile()->GetFileSpec().GetPath();
270 ModuleList symbol_modules = sym_file->GetDebugInfoModules();
271 for (const auto &symbol_module : symbol_modules.Modules())
272 module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
273 }
277 ++debug_index_loaded;
280 if (module_stat.debug_info_index_saved_to_cache)
281 ++debug_index_saved;
282 module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
283 module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
284 module_stat.debug_info_size =
285 sym_file->GetDebugInfoSize(load_all_debug_info);
286 module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
287 if (module_stat.symtab_stripped)
288 ++num_stripped_modules;
289 module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
290 module_stat.debug_info_size > 0;
293 if (module_stat.debug_info_enabled)
294 ++num_debug_info_enabled_modules;
295 if (module_stat.debug_info_size > 0)
296 ++num_modules_has_debug_info;
297 if (module_stat.debug_info_had_variable_errors)
298 ++num_modules_with_variable_errors;
299 }
300 symtab_parse_time += module_stat.symtab_parse_time;
301 symtab_index_time += module_stat.symtab_index_time;
302 debug_parse_time += module_stat.debug_parse_time;
303 debug_index_time += module_stat.debug_index_time;
304 debug_info_size += module_stat.debug_info_size;
305 module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
306 if (auto stats = ts->ReportStatistics())
307 module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
308 if (ts->GetHasForcefullyCompletedTypes())
309 module_stat.debug_info_had_incomplete_types = true;
310 return true;
311 });
312 if (module_stat.debug_info_had_incomplete_types)
313 ++num_modules_with_incomplete_types;
314
315 if (!summary_only) {
316 module_stat.identifier = (intptr_t)module;
317 module_stat.path = module->GetFileSpec().GetPath();
318 if (ConstString object_name = module->GetObjectName()) {
319 module_stat.path.append(1, '(');
320 module_stat.path.append(object_name.GetStringRef().str());
321 module_stat.path.append(1, ')');
322 }
323 module_stat.uuid = module->GetUUID().GetAsString();
324 module_stat.triple = module->GetArchitecture().GetTriple().str();
325 json_modules.emplace_back(module_stat.ToJSON());
326 }
327 }
328
329 json::Object global_stats{
330 {"totalSymbolTableParseTime", symtab_parse_time},
331 {"totalSymbolTableIndexTime", symtab_index_time},
332 {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
333 {"totalSymbolTablesSavedToCache", symtabs_saved},
334 {"totalDebugInfoParseTime", debug_parse_time},
335 {"totalDebugInfoIndexTime", debug_index_time},
336 {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
337 {"totalDebugInfoIndexSavedToCache", debug_index_saved},
338 {"totalDebugInfoByteSize", debug_info_size},
339 {"totalModuleCount", num_modules},
340 {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
341 {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
342 {"totalModuleCountWithIncompleteTypes",
343 num_modules_with_incomplete_types},
344 {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
345 {"totalSymbolTableStripped", num_stripped_modules},
346 };
347
348 if (target) {
349 json_targets.emplace_back(target->ReportStatistics(options));
350 } else {
351 for (const auto &target : debugger.GetTargetList().Targets())
352 json_targets.emplace_back(target->ReportStatistics(options));
353 }
354 global_stats.try_emplace("targets", std::move(json_targets));
355
356 if (!summary_only) {
357 ConstStringStats const_string_stats;
358 json::Object json_memory{
359 {"strings", const_string_stats.ToJSON()},
360 };
361 json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
362 global_stats.try_emplace("modules", std::move(json_modules));
363 global_stats.try_emplace("memory", std::move(json_memory));
364 global_stats.try_emplace("commands", std::move(cmd_stats));
365 }
366
367 return std::move(global_stats);
368}
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:38
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, const std::string &str)
Definition: Statistics.cpp:24
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.
const char * GetBreakpointKind() const
Return the "kind" description for a breakpoint.
Definition: Breakpoint.h:458
uint32_t GetHitCount() const
Return the current hit count for all locations.
Definition: Breakpoint.cpp:319
StatsDuration::Duration GetResolveTime() const
Get the time it took to resolve all locations in this breakpoint.
Definition: Breakpoint.h:592
A uniqued constant string class.
Definition: ConstString.h:40
static bool g_collecting_stats
Definition: Statistics.h:195
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target, const lldb_private::StatisticsOptions &options)
Get metrics associated with one or all targets in a debugger in JSON format.
Definition: Statistics.cpp:222
A class to manage flag bits.
Definition: Debugger.h:79
CommandInterpreter & GetCommandInterpreter()
Definition: Debugger.h:176
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:206
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:103
ModuleIterable Modules() const
Definition: ModuleList.h:527
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:1184
virtual SymbolFile * GetSymbolFile(bool can_create=true, Stream *feedback_strm=nullptr)
Get the module's symbol file.
Definition: Module.cpp:992
ConstString GetObjectName() const
Definition: Module.cpp:1182
static Module * GetAllocatedModuleAtIndex(size_t idx)
Definition: Module.cpp:124
static std::recursive_mutex & GetAllocationModuleCollectionMutex()
Definition: Module.cpp:106
Symtab * GetSymtab()
Definition: Module.cpp:1020
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:1035
StatsDuration & GetSymtabIndexTime()
Accessor for the symbol table index time metric.
Definition: Module.h:881
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:452
StatsDuration & GetSymtabParseTime()
Accessor for the symbol table parse time metric.
Definition: Module.h:875
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:50
virtual uint64_t GetDebugInfoSize(bool load_all_debug_info=false)=0
Metrics gathering functions.
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:408
virtual bool GetLoadDebugInfoEnabled()
Whether debug info will be loaded or not.
Definition: SymbolFile.h:135
virtual bool GetDebugInfoHadFrameVariableErrors() const =0
Accessors for the bool that indicates if there was debug info, but errors stopped variables from bein...
virtual ModuleList GetDebugInfoModules()
Get the additional modules that this symbol file uses to parse debug info.
Definition: SymbolFile.h:424
virtual StatsDuration::Duration GetDebugInfoIndexTime()
Return the time it took to index the debug information in the object file.
Definition: SymbolFile.h:415
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
StatsSuccessFail m_frame_var
Definition: Statistics.h:159
std::optional< StatsTimepoint > m_launch_or_attach_time
Definition: Statistics.h:155
uint32_t m_source_map_deduce_count
Definition: Statistics.h:161
void CollectStats(Target &target)
Definition: Statistics.cpp:44
llvm::json::Value ToJSON(Target &target, const lldb_private::StatisticsOptions &options)
Definition: Statistics.cpp:105
StatsDuration m_create_time
Definition: Statistics.h:154
std::optional< StatsTimepoint > m_first_public_stop_time
Definition: Statistics.h:157
StatsSuccessFail m_expr_eval
Definition: Statistics.h:158
std::vector< intptr_t > m_module_identifiers
Definition: Statistics.h:160
std::optional< StatsTimepoint > m_first_private_stop_time
Definition: Statistics.h:156
BreakpointList & GetBreakpointList(bool internal=false)
Definition: Target.cpp:314
const lldb::ProcessSP & GetProcessSP() const
Definition: Target.cpp:221
llvm::json::Value ReportStatistics(const lldb_private::StatisticsOptions &options)
Get metrics associated with this target in JSON format.
Definition: Target.cpp:4954
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:972
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:457
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
Definition: lldb-forward.h:468
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:365
Definition: Debugger.h:53
ConstString::MemoryStats stats
Definition: Statistics.h:130
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:96
A class that represents statistics for a since lldb_private::Module.
Definition: Statistics.h:99
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:50
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:34