[LoongArch][Clang] Make the parameters and return value of {x,}vorn.v builti ns ...
[llvm-project.git] / lldb / source / Target / Statistics.cpp
blob8173d20457e21b2c7fdbc138d204fcf0e24435a8
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 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/Statistics.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Interpreter/CommandInterpreter.h"
14 #include "lldb/Symbol/SymbolFile.h"
15 #include "lldb/Target/DynamicLoader.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Target/UnixSignals.h"
19 #include "lldb/Utility/StructuredData.h"
21 using namespace lldb;
22 using namespace lldb_private;
23 using namespace llvm;
25 static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
26 const std::string &str) {
27 if (str.empty())
28 return;
29 if (LLVM_LIKELY(llvm::json::isUTF8(str)))
30 obj.try_emplace(key, str);
31 else
32 obj.try_emplace(key, llvm::json::fixUTF8(str));
35 json::Value StatsSuccessFail::ToJSON() const {
36 return json::Object{{"successes", successes}, {"failures", failures}};
39 static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
40 StatsDuration::Duration elapsed =
41 end.time_since_epoch() - start.time_since_epoch();
42 return elapsed.count();
45 void TargetStats::CollectStats(Target &target) {
46 m_module_identifiers.clear();
47 for (ModuleSP module_sp : target.GetImages().Modules())
48 m_module_identifiers.emplace_back((intptr_t)module_sp.get());
51 json::Value ModuleStats::ToJSON() const {
52 json::Object module;
53 EmplaceSafeString(module, "path", path);
54 EmplaceSafeString(module, "uuid", uuid);
55 EmplaceSafeString(module, "triple", triple);
56 module.try_emplace("identifier", identifier);
57 module.try_emplace("symbolTableParseTime", symtab_parse_time);
58 module.try_emplace("symbolTableIndexTime", symtab_index_time);
59 module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
60 module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
61 module.try_emplace("debugInfoParseTime", debug_parse_time);
62 module.try_emplace("debugInfoIndexTime", debug_index_time);
63 module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
64 module.try_emplace("debugInfoIndexLoadedFromCache",
65 debug_info_index_loaded_from_cache);
66 module.try_emplace("debugInfoIndexSavedToCache",
67 debug_info_index_saved_to_cache);
68 module.try_emplace("debugInfoEnabled", debug_info_enabled);
69 module.try_emplace("debugInfoHadVariableErrors",
70 debug_info_had_variable_errors);
71 module.try_emplace("debugInfoHadIncompleteTypes",
72 debug_info_had_incomplete_types);
73 module.try_emplace("symbolTableStripped", symtab_stripped);
74 if (!symfile_path.empty())
75 module.try_emplace("symbolFilePath", symfile_path);
77 if (!symfile_modules.empty()) {
78 json::Array symfile_ids;
79 for (const auto symfile_id: symfile_modules)
80 symfile_ids.emplace_back(symfile_id);
81 module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
84 if (!type_system_stats.empty()) {
85 json::Array type_systems;
86 for (const auto &entry : type_system_stats) {
87 json::Object obj;
88 obj.try_emplace(entry.first().str(), entry.second);
89 type_systems.emplace_back(std::move(obj));
91 module.try_emplace("typeSystemInfo", std::move(type_systems));
94 return module;
97 llvm::json::Value ConstStringStats::ToJSON() const {
98 json::Object obj;
99 obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
100 obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
101 obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
102 return obj;
105 json::Value
106 TargetStats::ToJSON(Target &target,
107 const lldb_private::StatisticsOptions &options) {
108 json::Object target_metrics_json;
109 ProcessSP process_sp = target.GetProcessSP();
110 const bool summary_only = options.GetSummaryOnly();
111 const bool include_modules = options.GetIncludeModules();
112 if (!summary_only) {
113 CollectStats(target);
115 json::Array json_module_uuid_array;
116 for (auto module_identifier : m_module_identifiers)
117 json_module_uuid_array.emplace_back(module_identifier);
119 target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
120 target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
121 if (include_modules)
122 target_metrics_json.try_emplace("moduleIdentifiers",
123 std::move(json_module_uuid_array));
125 if (m_launch_or_attach_time && m_first_private_stop_time) {
126 double elapsed_time =
127 elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
128 target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
130 if (m_launch_or_attach_time && m_first_public_stop_time) {
131 double elapsed_time =
132 elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
133 target_metrics_json.try_emplace("firstStopTime", elapsed_time);
135 target_metrics_json.try_emplace("targetCreateTime",
136 m_create_time.get().count());
138 json::Array breakpoints_array;
139 double totalBreakpointResolveTime = 0.0;
140 // Report both the normal breakpoint list and the internal breakpoint list.
141 for (int i = 0; i < 2; ++i) {
142 BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
143 std::unique_lock<std::recursive_mutex> lock;
144 breakpoints.GetListMutex(lock);
145 size_t num_breakpoints = breakpoints.GetSize();
146 for (size_t i = 0; i < num_breakpoints; i++) {
147 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
148 breakpoints_array.push_back(bp->GetStatistics());
149 totalBreakpointResolveTime += bp->GetResolveTime().count();
152 target_metrics_json.try_emplace("breakpoints",
153 std::move(breakpoints_array));
154 target_metrics_json.try_emplace("totalBreakpointResolveTime",
155 totalBreakpointResolveTime);
157 if (process_sp) {
158 UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
159 if (unix_signals_sp)
160 target_metrics_json.try_emplace(
161 "signals", unix_signals_sp->GetHitCountStatistics());
165 // Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
166 // "shared-library-event".
168 uint32_t shared_library_event_breakpoint_hit_count = 0;
169 // The "shared-library-event" is only found in the internal breakpoint list.
170 BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
171 std::unique_lock<std::recursive_mutex> lock;
172 breakpoints.GetListMutex(lock);
173 size_t num_breakpoints = breakpoints.GetSize();
174 for (size_t i = 0; i < num_breakpoints; i++) {
175 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
176 if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
177 shared_library_event_breakpoint_hit_count += bp->GetHitCount();
180 target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
181 shared_library_event_breakpoint_hit_count);
184 if (process_sp) {
185 uint32_t stop_id = process_sp->GetStopID();
186 target_metrics_json.try_emplace("stopCount", stop_id);
188 llvm::StringRef dyld_plugin_name;
189 if (process_sp->GetDynamicLoader())
190 dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
191 target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
193 target_metrics_json.try_emplace("sourceMapDeduceCount",
194 m_source_map_deduce_count);
195 target_metrics_json.try_emplace("sourceRealpathAttemptCount",
196 m_source_realpath_attempt_count);
197 target_metrics_json.try_emplace("sourceRealpathCompatibleCount",
198 m_source_realpath_compatible_count);
199 target_metrics_json.try_emplace("summaryProviderStatistics",
200 target.GetSummaryStatisticsCache().ToJSON());
201 return target_metrics_json;
204 void TargetStats::Reset(Target &target) {
205 m_launch_or_attach_time.reset();
206 m_first_private_stop_time.reset();
207 m_first_public_stop_time.reset();
208 // Report both the normal breakpoint list and the internal breakpoint list.
209 for (int i = 0; i < 2; ++i) {
210 BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
211 std::unique_lock<std::recursive_mutex> lock;
212 breakpoints.GetListMutex(lock);
213 size_t num_breakpoints = breakpoints.GetSize();
214 for (size_t i = 0; i < num_breakpoints; i++) {
215 Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
216 bp->ResetStatistics();
219 target.GetSummaryStatisticsCache().Reset();
222 void TargetStats::SetLaunchOrAttachTime() {
223 m_launch_or_attach_time = StatsClock::now();
224 m_first_private_stop_time = std::nullopt;
227 void TargetStats::SetFirstPrivateStopTime() {
228 // Launching and attaching has many paths depending on if synchronous mode
229 // was used or if we are stopping at the entry point or not. Only set the
230 // first stop time if it hasn't already been set.
231 if (!m_first_private_stop_time)
232 m_first_private_stop_time = StatsClock::now();
235 void TargetStats::SetFirstPublicStopTime() {
236 // Launching and attaching has many paths depending on if synchronous mode
237 // was used or if we are stopping at the entry point or not. Only set the
238 // first stop time if it hasn't already been set.
239 if (!m_first_public_stop_time)
240 m_first_public_stop_time = StatsClock::now();
243 void TargetStats::IncreaseSourceMapDeduceCount() {
244 ++m_source_map_deduce_count;
247 void TargetStats::IncreaseSourceRealpathAttemptCount(uint32_t count) {
248 m_source_realpath_attempt_count += count;
251 void TargetStats::IncreaseSourceRealpathCompatibleCount(uint32_t count) {
252 m_source_realpath_compatible_count += count;
255 bool DebuggerStats::g_collecting_stats = false;
257 void DebuggerStats::ResetStatistics(Debugger &debugger, Target *target) {
258 std::lock_guard<std::recursive_mutex> guard(
259 Module::GetAllocationModuleCollectionMutex());
260 const uint64_t num_modules = target != nullptr
261 ? target->GetImages().GetSize()
262 : Module::GetNumberAllocatedModules();
263 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
264 Module *module = target != nullptr
265 ? target->GetImages().GetModuleAtIndex(image_idx).get()
266 : Module::GetAllocatedModuleAtIndex(image_idx);
267 if (module == nullptr)
268 continue;
269 module->ResetStatistics();
271 if (target)
272 target->ResetStatistics();
273 else {
274 for (const auto &target : debugger.GetTargetList().Targets())
275 target->ResetStatistics();
279 llvm::json::Value DebuggerStats::ReportStatistics(
280 Debugger &debugger, Target *target,
281 const lldb_private::StatisticsOptions &options) {
283 const bool summary_only = options.GetSummaryOnly();
284 const bool load_all_debug_info = options.GetLoadAllDebugInfo();
285 const bool include_targets = options.GetIncludeTargets();
286 const bool include_modules = options.GetIncludeModules();
287 const bool include_transcript = options.GetIncludeTranscript();
289 json::Array json_targets;
290 json::Array json_modules;
291 double symtab_parse_time = 0.0;
292 double symtab_index_time = 0.0;
293 double debug_parse_time = 0.0;
294 double debug_index_time = 0.0;
295 uint32_t symtabs_loaded = 0;
296 uint32_t symtabs_saved = 0;
297 uint32_t debug_index_loaded = 0;
298 uint32_t debug_index_saved = 0;
299 uint64_t debug_info_size = 0;
301 std::vector<ModuleStats> modules;
302 std::lock_guard<std::recursive_mutex> guard(
303 Module::GetAllocationModuleCollectionMutex());
304 const uint64_t num_modules = target != nullptr
305 ? target->GetImages().GetSize()
306 : Module::GetNumberAllocatedModules();
307 uint32_t num_debug_info_enabled_modules = 0;
308 uint32_t num_modules_has_debug_info = 0;
309 uint32_t num_modules_with_variable_errors = 0;
310 uint32_t num_modules_with_incomplete_types = 0;
311 uint32_t num_stripped_modules = 0;
312 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
313 Module *module = target != nullptr
314 ? target->GetImages().GetModuleAtIndex(image_idx).get()
315 : Module::GetAllocatedModuleAtIndex(image_idx);
316 ModuleStats module_stat;
317 module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
318 module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
319 Symtab *symtab = module->GetSymtab();
320 if (symtab) {
321 module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
322 if (module_stat.symtab_loaded_from_cache)
323 ++symtabs_loaded;
324 module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
325 if (module_stat.symtab_saved_to_cache)
326 ++symtabs_saved;
328 SymbolFile *sym_file = module->GetSymbolFile();
329 if (sym_file) {
330 if (!summary_only) {
331 if (sym_file->GetObjectFile() != module->GetObjectFile())
332 module_stat.symfile_path =
333 sym_file->GetObjectFile()->GetFileSpec().GetPath();
334 ModuleList symbol_modules = sym_file->GetDebugInfoModules();
335 for (const auto &symbol_module : symbol_modules.Modules())
336 module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
338 module_stat.debug_info_index_loaded_from_cache =
339 sym_file->GetDebugInfoIndexWasLoadedFromCache();
340 if (module_stat.debug_info_index_loaded_from_cache)
341 ++debug_index_loaded;
342 module_stat.debug_info_index_saved_to_cache =
343 sym_file->GetDebugInfoIndexWasSavedToCache();
344 if (module_stat.debug_info_index_saved_to_cache)
345 ++debug_index_saved;
346 module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
347 module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
348 module_stat.debug_info_size =
349 sym_file->GetDebugInfoSize(load_all_debug_info);
350 module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
351 if (module_stat.symtab_stripped)
352 ++num_stripped_modules;
353 module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
354 module_stat.debug_info_size > 0;
355 module_stat.debug_info_had_variable_errors =
356 sym_file->GetDebugInfoHadFrameVariableErrors();
357 if (module_stat.debug_info_enabled)
358 ++num_debug_info_enabled_modules;
359 if (module_stat.debug_info_size > 0)
360 ++num_modules_has_debug_info;
361 if (module_stat.debug_info_had_variable_errors)
362 ++num_modules_with_variable_errors;
364 symtab_parse_time += module_stat.symtab_parse_time;
365 symtab_index_time += module_stat.symtab_index_time;
366 debug_parse_time += module_stat.debug_parse_time;
367 debug_index_time += module_stat.debug_index_time;
368 debug_info_size += module_stat.debug_info_size;
369 module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
370 if (auto stats = ts->ReportStatistics())
371 module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
372 if (ts->GetHasForcefullyCompletedTypes())
373 module_stat.debug_info_had_incomplete_types = true;
374 return true;
376 if (module_stat.debug_info_had_incomplete_types)
377 ++num_modules_with_incomplete_types;
379 if (include_modules) {
380 module_stat.identifier = (intptr_t)module;
381 module_stat.path = module->GetFileSpec().GetPath();
382 if (ConstString object_name = module->GetObjectName()) {
383 module_stat.path.append(1, '(');
384 module_stat.path.append(object_name.GetStringRef().str());
385 module_stat.path.append(1, ')');
387 module_stat.uuid = module->GetUUID().GetAsString();
388 module_stat.triple = module->GetArchitecture().GetTriple().str();
389 json_modules.emplace_back(module_stat.ToJSON());
393 json::Object global_stats{
394 {"totalSymbolTableParseTime", symtab_parse_time},
395 {"totalSymbolTableIndexTime", symtab_index_time},
396 {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
397 {"totalSymbolTablesSavedToCache", symtabs_saved},
398 {"totalDebugInfoParseTime", debug_parse_time},
399 {"totalDebugInfoIndexTime", debug_index_time},
400 {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
401 {"totalDebugInfoIndexSavedToCache", debug_index_saved},
402 {"totalDebugInfoByteSize", debug_info_size},
403 {"totalModuleCount", num_modules},
404 {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
405 {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
406 {"totalModuleCountWithIncompleteTypes",
407 num_modules_with_incomplete_types},
408 {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
409 {"totalSymbolTableStripped", num_stripped_modules},
412 if (include_targets) {
413 if (target) {
414 json_targets.emplace_back(target->ReportStatistics(options));
415 } else {
416 for (const auto &target : debugger.GetTargetList().Targets())
417 json_targets.emplace_back(target->ReportStatistics(options));
419 global_stats.try_emplace("targets", std::move(json_targets));
422 ConstStringStats const_string_stats;
423 json::Object json_memory{
424 {"strings", const_string_stats.ToJSON()},
426 global_stats.try_emplace("memory", std::move(json_memory));
427 if (!summary_only) {
428 json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
429 global_stats.try_emplace("commands", std::move(cmd_stats));
432 if (include_modules) {
433 global_stats.try_emplace("modules", std::move(json_modules));
436 if (include_transcript) {
437 // When transcript is available, add it to the to-be-returned statistics.
439 // NOTE:
440 // When the statistics is polled by an LLDB command:
441 // - The transcript in the returned statistics *will NOT* contain the
442 // returned statistics itself (otherwise infinite recursion).
443 // - The returned statistics *will* be written to the internal transcript
444 // buffer. It *will* appear in the next statistcs or transcript poll.
446 // For example, let's say the following commands are run in order:
447 // - "version"
448 // - "statistics dump" <- call it "A"
449 // - "statistics dump" <- call it "B"
450 // The output of "A" will contain the transcript of "version" and
451 // "statistics dump" (A), with the latter having empty output. The output
452 // of B will contain the trascnript of "version", "statistics dump" (A),
453 // "statistics dump" (B), with A's output populated and B's output empty.
454 const StructuredData::Array &transcript =
455 debugger.GetCommandInterpreter().GetTranscript();
456 if (transcript.GetSize() != 0) {
457 std::string buffer;
458 llvm::raw_string_ostream ss(buffer);
459 json::OStream json_os(ss);
460 transcript.Serialize(json_os);
461 if (auto json_transcript = llvm::json::parse(buffer))
462 global_stats.try_emplace("transcript",
463 std::move(json_transcript.get()));
467 return std::move(global_stats);
470 llvm::json::Value SummaryStatistics::ToJSON() const {
471 return json::Object{{
472 {"name", GetName()},
473 {"type", GetSummaryKindName()},
474 {"count", GetSummaryCount()},
475 {"totalTime", GetTotalTime()},
479 json::Value SummaryStatisticsCache::ToJSON() {
480 std::lock_guard<std::mutex> guard(m_map_mutex);
481 json::Array json_summary_stats;
482 for (const auto &summary_stat : m_summary_stats_map)
483 json_summary_stats.emplace_back(summary_stat.second->ToJSON());
485 return json_summary_stats;
488 void SummaryStatisticsCache::Reset() {
489 for (const auto &summary_stat : m_summary_stats_map)
490 summary_stat.second->Reset();