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 9 #include "lldb/Target/Statistics.h" 10 11 #include "lldb/Core/Debugger.h" 12 #include "lldb/Core/Module.h" 13 #include "lldb/Symbol/SymbolFile.h" 14 #include "lldb/Target/Target.h" 15 16 using namespace lldb; 17 using namespace lldb_private; 18 using namespace llvm; 19 20 static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, 21 const std::string &str) { 22 if (str.empty()) 23 return; 24 if (LLVM_LIKELY(llvm::json::isUTF8(str))) 25 obj.try_emplace(key, str); 26 else 27 obj.try_emplace(key, llvm::json::fixUTF8(str)); 28 } 29 30 json::Value StatsSuccessFail::ToJSON() const { 31 return json::Object{{"successes", successes}, {"failures", failures}}; 32 } 33 34 static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) { 35 StatsDuration elapsed = end.time_since_epoch() - start.time_since_epoch(); 36 return elapsed.count(); 37 } 38 39 void TargetStats::CollectStats(Target &target) { 40 m_module_identifiers.clear(); 41 for (ModuleSP module_sp : target.GetImages().Modules()) 42 m_module_identifiers.emplace_back((intptr_t)module_sp.get()); 43 } 44 45 json::Value ModuleStats::ToJSON() const { 46 json::Object module; 47 EmplaceSafeString(module, "path", path); 48 EmplaceSafeString(module, "uuid", uuid); 49 EmplaceSafeString(module, "triple", triple); 50 module.try_emplace("identifier", identifier); 51 module.try_emplace("symbolTableParseTime", symtab_parse_time); 52 module.try_emplace("symbolTableIndexTime", symtab_index_time); 53 module.try_emplace("debugInfoParseTime", debug_parse_time); 54 module.try_emplace("debugInfoIndexTime", debug_index_time); 55 module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size); 56 return module; 57 } 58 59 json::Value TargetStats::ToJSON(Target &target) { 60 CollectStats(target); 61 62 json::Array json_module_uuid_array; 63 for (auto module_identifier : m_module_identifiers) 64 json_module_uuid_array.emplace_back(module_identifier); 65 66 json::Object target_metrics_json{ 67 {m_expr_eval.name, m_expr_eval.ToJSON()}, 68 {m_frame_var.name, m_frame_var.ToJSON()}, 69 {"moduleIdentifiers", std::move(json_module_uuid_array)}}; 70 71 if (m_launch_or_attach_time && m_first_private_stop_time) { 72 double elapsed_time = 73 elapsed(*m_launch_or_attach_time, *m_first_private_stop_time); 74 target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time); 75 } 76 if (m_launch_or_attach_time && m_first_public_stop_time) { 77 double elapsed_time = 78 elapsed(*m_launch_or_attach_time, *m_first_public_stop_time); 79 target_metrics_json.try_emplace("firstStopTime", elapsed_time); 80 } 81 target_metrics_json.try_emplace("targetCreateTime", m_create_time.count()); 82 83 return target_metrics_json; 84 } 85 86 void TargetStats::SetLaunchOrAttachTime() { 87 m_launch_or_attach_time = StatsClock::now(); 88 m_first_private_stop_time = llvm::None; 89 } 90 91 void TargetStats::SetFirstPrivateStopTime() { 92 // Launching and attaching has many paths depending on if synchronous mode 93 // was used or if we are stopping at the entry point or not. Only set the 94 // first stop time if it hasn't already been set. 95 if (!m_first_private_stop_time) 96 m_first_private_stop_time = StatsClock::now(); 97 } 98 99 void TargetStats::SetFirstPublicStopTime() { 100 // Launching and attaching has many paths depending on if synchronous mode 101 // was used or if we are stopping at the entry point or not. Only set the 102 // first stop time if it hasn't already been set. 103 if (!m_first_public_stop_time) 104 m_first_public_stop_time = StatsClock::now(); 105 } 106 107 bool DebuggerStats::g_collecting_stats = false; 108 109 llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, 110 Target *target) { 111 json::Array json_targets; 112 json::Array json_modules; 113 double symtab_parse_time = 0.0; 114 double symtab_index_time = 0.0; 115 double debug_parse_time = 0.0; 116 double debug_index_time = 0.0; 117 uint64_t debug_info_size = 0; 118 if (target) { 119 json_targets.emplace_back(target->ReportStatistics()); 120 } else { 121 for (const auto &target : debugger.GetTargetList().Targets()) 122 json_targets.emplace_back(target->ReportStatistics()); 123 } 124 std::vector<ModuleStats> modules; 125 std::lock_guard<std::recursive_mutex> guard( 126 Module::GetAllocationModuleCollectionMutex()); 127 const size_t num_modules = Module::GetNumberAllocatedModules(); 128 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { 129 Module *module = Module::GetAllocatedModuleAtIndex(image_idx); 130 ModuleStats module_stat; 131 module_stat.identifier = (intptr_t)module; 132 module_stat.path = module->GetFileSpec().GetPath(); 133 if (ConstString object_name = module->GetObjectName()) { 134 module_stat.path.append(1, '('); 135 module_stat.path.append(object_name.GetStringRef().str()); 136 module_stat.path.append(1, ')'); 137 } 138 module_stat.uuid = module->GetUUID().GetAsString(); 139 module_stat.triple = module->GetArchitecture().GetTriple().str(); 140 module_stat.symtab_parse_time = module->GetSymtabParseTime().count(); 141 module_stat.symtab_index_time = module->GetSymtabIndexTime().count(); 142 SymbolFile *sym_file = module->GetSymbolFile(); 143 if (sym_file) { 144 module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count(); 145 module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count(); 146 module_stat.debug_info_size = sym_file->GetDebugInfoSize(); 147 } 148 symtab_parse_time += module_stat.symtab_parse_time; 149 symtab_index_time += module_stat.symtab_index_time; 150 debug_parse_time += module_stat.debug_parse_time; 151 debug_index_time += module_stat.debug_index_time; 152 debug_info_size += module_stat.debug_info_size; 153 json_modules.emplace_back(module_stat.ToJSON()); 154 } 155 156 json::Object global_stats{ 157 {"targets", std::move(json_targets)}, 158 {"modules", std::move(json_modules)}, 159 {"totalSymbolTableParseTime", symtab_parse_time}, 160 {"totalSymbolTableIndexTime", symtab_index_time}, 161 {"totalDebugInfoParseTime", debug_parse_time}, 162 {"totalDebugInfoIndexTime", debug_index_time}, 163 {"totalDebugInfoByteSize", debug_info_size}, 164 }; 165 return std::move(global_stats); 166 } 167