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"
13 #include "lldb/Symbol/SymbolFile.h"
14 #include "lldb/Target/Process.h"
15 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 using namespace llvm;
21 
22 static 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 
32 json::Value StatsSuccessFail::ToJSON() const {
33  return json::Object{{"successes", successes}, {"failures", failures}};
34 }
35 
36 static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
38  end.time_since_epoch() - start.time_since_epoch();
39  return elapsed.count();
40 }
41 
42 void TargetStats::CollectStats(Target &target) {
43  m_module_identifiers.clear();
44  for (ModuleSP module_sp : target.GetImages().Modules())
45  m_module_identifiers.emplace_back((intptr_t)module_sp.get());
46 }
47 
48 json::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",
62  debug_info_index_loaded_from_cache);
63  module.try_emplace("debugInfoIndexSavedToCache",
64  debug_info_index_saved_to_cache);
65  module.try_emplace("debugInfoEnabled", debug_info_enabled);
66  module.try_emplace("debugInfoHadVariableErrors",
67  debug_info_had_variable_errors);
68  module.try_emplace("symbolTableStripped", symtab_stripped);
69  if (!symfile_path.empty())
70  module.try_emplace("symbolFilePath", symfile_path);
71 
72  if (!symfile_modules.empty()) {
73  json::Array symfile_ids;
74  for (const auto symfile_id: symfile_modules)
75  symfile_ids.emplace_back(symfile_id);
76  module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
77  }
78 
79  if (!type_system_stats.empty()) {
80  json::Array type_systems;
81  for (const auto &entry : type_system_stats) {
82  json::Object obj;
83  obj.try_emplace(entry.first().str(), entry.second);
84  type_systems.emplace_back(std::move(obj));
85  }
86  module.try_emplace("typeSystemInfo", std::move(type_systems));
87  }
88 
89  return module;
90 }
91 
92 llvm::json::Value ConstStringStats::ToJSON() const {
93  json::Object obj;
94  obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
95  obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
96  obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
97  return obj;
98 }
99 
100 json::Value TargetStats::ToJSON(Target &target) {
101  CollectStats(target);
102 
103  json::Array json_module_uuid_array;
104  for (auto module_identifier : m_module_identifiers)
105  json_module_uuid_array.emplace_back(module_identifier);
106 
107  json::Object target_metrics_json{
108  {m_expr_eval.name, m_expr_eval.ToJSON()},
109  {m_frame_var.name, m_frame_var.ToJSON()},
110  {"moduleIdentifiers", std::move(json_module_uuid_array)}};
111 
112  if (m_launch_or_attach_time && m_first_private_stop_time) {
113  double elapsed_time =
114  elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
115  target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
116  }
117  if (m_launch_or_attach_time && m_first_public_stop_time) {
118  double elapsed_time =
119  elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
120  target_metrics_json.try_emplace("firstStopTime", elapsed_time);
121  }
122  target_metrics_json.try_emplace("targetCreateTime",
123  m_create_time.get().count());
124 
125  json::Array breakpoints_array;
126  double totalBreakpointResolveTime = 0.0;
127  // Rport both the normal breakpoint list and the internal breakpoint list.
128  for (int i = 0; i < 2; ++i) {
129  BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
130  std::unique_lock<std::recursive_mutex> lock;
131  breakpoints.GetListMutex(lock);
132  size_t num_breakpoints = breakpoints.GetSize();
133  for (size_t i = 0; i < num_breakpoints; i++) {
134  Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
135  breakpoints_array.push_back(bp->GetStatistics());
136  totalBreakpointResolveTime += bp->GetResolveTime().count();
137  }
138  }
139 
140  ProcessSP process_sp = target.GetProcessSP();
141  if (process_sp) {
142  UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
143  if (unix_signals_sp)
144  target_metrics_json.try_emplace("signals",
145  unix_signals_sp->GetHitCountStatistics());
146  uint32_t stop_id = process_sp->GetStopID();
147  target_metrics_json.try_emplace("stopCount", stop_id);
148  }
149  target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array));
150  target_metrics_json.try_emplace("totalBreakpointResolveTime",
151  totalBreakpointResolveTime);
152  target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count);
153 
154  return target_metrics_json;
155 }
156 
157 void TargetStats::SetLaunchOrAttachTime() {
158  m_launch_or_attach_time = StatsClock::now();
159  m_first_private_stop_time = llvm::None;
160 }
161 
162 void TargetStats::SetFirstPrivateStopTime() {
163  // Launching and attaching has many paths depending on if synchronous mode
164  // was used or if we are stopping at the entry point or not. Only set the
165  // first stop time if it hasn't already been set.
166  if (!m_first_private_stop_time)
167  m_first_private_stop_time = StatsClock::now();
168 }
169 
170 void TargetStats::SetFirstPublicStopTime() {
171  // Launching and attaching has many paths depending on if synchronous mode
172  // was used or if we are stopping at the entry point or not. Only set the
173  // first stop time if it hasn't already been set.
174  if (!m_first_public_stop_time)
175  m_first_public_stop_time = StatsClock::now();
176 }
177 
178 void TargetStats::IncreaseSourceMapDeduceCount() {
179  ++m_source_map_deduce_count;
180 }
181 
182 bool DebuggerStats::g_collecting_stats = false;
183 
184 llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
185  Target *target) {
186  json::Array json_targets;
187  json::Array json_modules;
188  double symtab_parse_time = 0.0;
189  double symtab_index_time = 0.0;
190  double debug_parse_time = 0.0;
191  double debug_index_time = 0.0;
192  uint32_t symtabs_loaded = 0;
193  uint32_t symtabs_saved = 0;
194  uint32_t debug_index_loaded = 0;
195  uint32_t debug_index_saved = 0;
196  uint64_t debug_info_size = 0;
197  if (target) {
198  json_targets.emplace_back(target->ReportStatistics());
199  } else {
200  for (const auto &target : debugger.GetTargetList().Targets())
201  json_targets.emplace_back(target->ReportStatistics());
202  }
203  std::vector<ModuleStats> modules;
204  std::lock_guard<std::recursive_mutex> guard(
205  Module::GetAllocationModuleCollectionMutex());
206  const uint64_t num_modules = Module::GetNumberAllocatedModules();
207  uint32_t num_debug_info_enabled_modules = 0;
208  uint32_t num_modules_has_debug_info = 0;
209  uint32_t num_modules_with_variable_errors = 0;
210  uint32_t num_stripped_modules = 0;
211  for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
212  Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
213  ModuleStats module_stat;
214  module_stat.identifier = (intptr_t)module;
215  module_stat.path = module->GetFileSpec().GetPath();
216  if (ConstString object_name = module->GetObjectName()) {
217  module_stat.path.append(1, '(');
218  module_stat.path.append(object_name.GetStringRef().str());
219  module_stat.path.append(1, ')');
220  }
221  module_stat.uuid = module->GetUUID().GetAsString();
222  module_stat.triple = module->GetArchitecture().GetTriple().str();
223  module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
224  module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
225  Symtab *symtab = module->GetSymtab();
226  if (symtab) {
227  module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
228  if (module_stat.symtab_loaded_from_cache)
229  ++symtabs_loaded;
230  module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
231  if (module_stat.symtab_saved_to_cache)
232  ++symtabs_saved;
233  }
234  SymbolFile *sym_file = module->GetSymbolFile();
235  if (sym_file) {
236 
237  if (sym_file->GetObjectFile() != module->GetObjectFile())
238  module_stat.symfile_path =
239  sym_file->GetObjectFile()->GetFileSpec().GetPath();
240  module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
241  module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
242  module_stat.debug_info_size = sym_file->GetDebugInfoSize();
245  if (module_stat.debug_info_index_loaded_from_cache)
246  ++debug_index_loaded;
247  module_stat.debug_info_index_saved_to_cache =
249  if (module_stat.debug_info_index_saved_to_cache)
250  ++debug_index_saved;
251  ModuleList symbol_modules = sym_file->GetDebugInfoModules();
252  for (const auto &symbol_module: symbol_modules.Modules())
253  module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
254  module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
255  if (module_stat.symtab_stripped)
256  ++num_stripped_modules;
257  module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
258  module_stat.debug_info_size > 0;
259  module_stat.debug_info_had_variable_errors =
261  if (module_stat.debug_info_enabled)
262  ++num_debug_info_enabled_modules;
263  if (module_stat.debug_info_size > 0)
264  ++num_modules_has_debug_info;
265  if (module_stat.debug_info_had_variable_errors)
266  ++num_modules_with_variable_errors;
267  }
268  symtab_parse_time += module_stat.symtab_parse_time;
269  symtab_index_time += module_stat.symtab_index_time;
270  debug_parse_time += module_stat.debug_parse_time;
271  debug_index_time += module_stat.debug_index_time;
272  debug_info_size += module_stat.debug_info_size;
273  module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
274  if (auto stats = ts->ReportStatistics())
275  module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
276  return true;
277  });
278  json_modules.emplace_back(module_stat.ToJSON());
279  }
280 
281  ConstStringStats const_string_stats;
282  json::Object json_memory{
283  {"strings", const_string_stats.ToJSON()},
284  };
285 
286  json::Object global_stats{
287  {"targets", std::move(json_targets)},
288  {"modules", std::move(json_modules)},
289  {"memory", std::move(json_memory)},
290  {"totalSymbolTableParseTime", symtab_parse_time},
291  {"totalSymbolTableIndexTime", symtab_index_time},
292  {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
293  {"totalSymbolTablesSavedToCache", symtabs_saved},
294  {"totalDebugInfoParseTime", debug_parse_time},
295  {"totalDebugInfoIndexTime", debug_index_time},
296  {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
297  {"totalDebugInfoIndexSavedToCache", debug_index_saved},
298  {"totalDebugInfoByteSize", debug_info_size},
299  {"totalModuleCount", num_modules},
300  {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
301  {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
302  {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
303  {"totalSymbolTableStripped", num_stripped_modules},
304  };
305  return std::move(global_stats);
306 }
lldb_private::Breakpoint::GetStatistics
llvm::json::Value GetStatistics()
Get statistics associated with this breakpoint in JSON format.
Definition: Breakpoint.cpp:1129
lldb_private::ModuleStats::ToJSON
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:48
lldb_private::Module::GetObjectFile
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
Definition: Module.cpp:1268
lldb_private::SymbolFile
Provides public interface for all SymbolFiles.
Definition: SymbolFile.h:46
llvm
Definition: Debugger.h:50
lldb_private::BreakpointList
General Outline: Allows adding and removing breakpoints and find by ID and index.
Definition: BreakpointList.h:25
lldb_private::Module::GetSymtabIndexTime
StatsDuration & GetSymtabIndexTime()
Accessor for the symbol table index time metric.
Definition: Module.h:913
lldb_private::ObjectFile::GetFileSpec
virtual FileSpec & GetFileSpec()
Get accessor to the object file specification.
Definition: ObjectFile.h:292
lldb_private::Module::GetSymtabParseTime
StatsDuration & GetSymtabParseTime()
Accessor for the symbol table parse time metric.
Definition: Module.h:907
lldb_private::ModuleStats::debug_info_index_loaded_from_cache
bool debug_info_index_loaded_from_cache
Definition: Statistics.h:119
lldb_private::ModuleList::Modules
ModuleIterable Modules() const
Definition: ModuleList.h:494
lldb_private::SymbolFile::GetDebugInfoIndexTime
virtual StatsDuration::Duration GetDebugInfoIndexTime()
Return the time it took to index the debug information in the object file.
Definition: SymbolFile.h:382
lldb_private::Symtab::GetWasSavedToCache
bool GetWasSavedToCache() const
Definition: Symtab.h:234
lldb_private::ModuleStats::debug_info_index_saved_to_cache
bool debug_info_index_saved_to_cache
Definition: Statistics.h:120
lldb_private::Module::GetSymtab
Symtab * GetSymtab()
Definition: Module.cpp:1069
lldb_private::ModuleStats::type_system_stats
llvm::StringMap< llvm::json::Value > type_system_stats
Definition: Statistics.h:111
lldb_private::StatsDuration::Duration
std::chrono::duration< double > Duration
Definition: Statistics.h:30
lldb_private::ModuleStats::symtab_stripped
bool symtab_stripped
Definition: Statistics.h:122
lldb_private::ModuleStats::symtab_saved_to_cache
bool symtab_saved_to_cache
Definition: Statistics.h:118
Module.h
lldb_private::ModuleStats::triple
std::string triple
Definition: Statistics.h:103
EmplaceSafeString
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key, const std::string &str)
Definition: Statistics.cpp:22
lldb_private::Module::GetSymbolFile
virtual SymbolFile * GetSymbolFile(bool can_create=true, Stream *feedback_strm=nullptr)
Get the module's symbol file.
Definition: Module.cpp:1053
lldb_private::Module
Definition: Module.h:86
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:463
lldb_private::Target::GetBreakpointList
BreakpointList & GetBreakpointList(bool internal=false)
Definition: Target.cpp:311
lldb_private::ModuleStats::symtab_loaded_from_cache
bool symtab_loaded_from_cache
Definition: Statistics.h:117
lldb_private::ModuleStats::identifier
intptr_t identifier
Definition: Statistics.h:100
lldb_private::ModuleStats::debug_parse_time
double debug_parse_time
Definition: Statistics.h:114
Debugger.h
lldb_private::Target
Definition: Target.h:469
lldb_private::ConstStringStats
Definition: Statistics.h:126
lldb_private::Target::GetImages
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:947
lldb_private::UUID::GetAsString
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:49
lldb_private::ModuleStats::symtab_index_time
double symtab_index_time
Definition: Statistics.h:113
Process.h
lldb_private::Module::ForEachTypeSystem
void ForEachTypeSystem(llvm::function_ref< bool(lldb::TypeSystemSP)> callback)
Call callback for each TypeSystem in this Module.
Definition: Module.cpp:372
Target.h
lldb_private::Module::GetFileSpec
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:497
elapsed
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:36
lldb_private::ModuleStats::debug_info_had_variable_errors
bool debug_info_had_variable_errors
Definition: Statistics.h:123
lldb_private::ModuleStats
A class that represents statistics for a since lldb_private::Module.
Definition: Statistics.h:98
lldb_private::ModuleList
Definition: ModuleList.h:82
UnixSignals.h
lldb_private::ModuleStats::symfile_modules
std::vector< intptr_t > symfile_modules
Definition: Statistics.h:110
lldb_private::ModuleStats::symfile_path
std::string symfile_path
Definition: Statistics.h:105
lldb_private::ModuleStats::debug_info_enabled
bool debug_info_enabled
Definition: Statistics.h:121
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::Module::GetObjectName
ConstString GetObjectName() const
Definition: Module.cpp:1266
lldb_private::SymbolFile::GetLoadDebugInfoEnabled
virtual bool GetLoadDebugInfoEnabled()
Whether debug info will be loaded or not.
Definition: SymbolFile.h:131
lldb_private::Debugger
Definition: Debugger.h:74
lldb_private::ModuleStats::debug_info_size
uint64_t debug_info_size
Definition: Statistics.h:116
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::ObjectFile::IsStripped
virtual bool IsStripped()=0
Detect if this object file has been stripped of local symbols.
lldb_private::BreakpointList::GetListMutex
void GetListMutex(std::unique_lock< std::recursive_mutex > &lock)
Sets the passed in Locker to hold the Breakpoint List mutex.
Definition: BreakpointList.cpp:195
lldb_private::SymbolFile::GetDebugInfoSize
virtual uint64_t GetDebugInfoSize()=0
Metrics gathering functions.
lldb_private::Debugger::GetTargetList
TargetList & GetTargetList()
Get accessor for the target list.
Definition: Debugger.h:199
lldb_private::Breakpoint::GetResolveTime
StatsDuration::Duration GetResolveTime() const
Get the time it took to resolve all locations in this breakpoint.
Definition: Breakpoint.h:594
lldb_private::ModuleStats::uuid
std::string uuid
Definition: Statistics.h:102
lldb_private::StatsTimepoint
std::chrono::time_point< StatsClock > StatsTimepoint
Definition: Statistics.h:26
lldb_private::Target::GetProcessSP
const lldb::ProcessSP & GetProcessSP() const
Definition: Target.cpp:219
lldb_private::TargetList::Targets
TargetIterable Targets()
Definition: TargetList.h:188
lldb_private::BreakpointList::GetBreakpointAtIndex
lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const
Returns a shared pointer to the breakpoint with index i.
Definition: BreakpointList.cpp:162
lldb_private::Symtab
Definition: Symtab.h:22
lldb_private::SymbolFile::GetDebugInfoIndexWasSavedToCache
virtual bool GetDebugInfoIndexWasSavedToCache() const =0
uint32_t
lldb_private::SymbolFile::GetDebugInfoParseTime
virtual StatsDuration::Duration GetDebugInfoParseTime()
Return the time taken to parse the debug information.
Definition: SymbolFile.h:375
lldb_private::ModuleStats::path
std::string path
Definition: Statistics.h:101
lldb_private::ModuleStats::symtab_parse_time
double symtab_parse_time
Definition: Statistics.h:112
lldb_private::StatsDuration::get
Duration get() const
Definition: Statistics.h:32
lldb_private::Symtab::GetWasLoadedFromCache
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
lldb_private::BreakpointList::GetSize
size_t GetSize() const
Returns the number of elements in this breakpoint list.
Definition: BreakpointList.h:79
Statistics.h
lldb_private::SymbolFile::GetDebugInfoHadFrameVariableErrors
virtual bool GetDebugInfoHadFrameVariableErrors() const =0
Accessors for the bool that indicates if there was debug info, but errors stopped variables from bein...
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::ConstStringStats::ToJSON
llvm::json::Value ToJSON() const
Definition: Statistics.cpp:92
lldb_private::ModuleStats::debug_index_time
double debug_index_time
Definition: Statistics.h:115
lldb_private::SymbolFile::GetDebugInfoModules
virtual ModuleList GetDebugInfoModules()
Get the additional modules that this symbol file uses to parse debug info.
Definition: SymbolFile.h:391
lldb_private::Module::GetArchitecture
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1084
lldb_private::Module::GetUUID
const lldb_private::UUID & GetUUID()
Get a reference to the UUID value contained in this object.
Definition: Module.cpp:342
lldb_private::SymbolFile::GetObjectFile
virtual ObjectFile * GetObjectFile()=0
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:364
lldb
Definition: SBAddress.h:15
lldb_private::Target::ReportStatistics
llvm::json::Value ReportStatistics()
Get metrics associated with this target in JSON format.
Definition: Target.cpp:4812
lldb_private::SymbolFile::GetDebugInfoIndexWasLoadedFromCache
virtual bool GetDebugInfoIndexWasLoadedFromCache() const =0
Accessors for the bool that indicates if the debug info index was loaded from, or saved to the module...
SymbolFile.h
lldb_private::Breakpoint
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
Definition: Breakpoint.h:80