Skip to content

Commit e5902ab

Browse files
committed
Support statistics dump summary only mode
Summary: Added a new --summary option to statistics dump command so that it is much light weight than the full version. With this change, statistics dump --summary can now be included in lldb command line telemetry without slowing down lldb exiting.
1 parent 16d890c commit e5902ab

File tree

9 files changed

+163
-87
lines changed

9 files changed

+163
-87
lines changed

lldb/include/lldb/API/SBTarget.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,13 @@ class LLDB_API SBTarget {
8686

8787
/// Returns a dump of the collected statistics.
8888
///
89+
/// \param[in] summary_only
90+
/// If true, only report high level summary statistics without
91+
/// targets/modules/breakpoints etc.. details.
92+
///
8993
/// \return
9094
/// A SBStructuredData with the statistics collected.
91-
lldb::SBStructuredData GetStatistics();
95+
lldb::SBStructuredData GetStatistics(bool summary_only = false);
9296

9397
/// Return the platform object associated with the target.
9498
///

lldb/include/lldb/Target/Statistics.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct ConstStringStats {
133133
/// A class that represents statistics for a since lldb_private::Target.
134134
class TargetStats {
135135
public:
136-
llvm::json::Value ToJSON(Target &target);
136+
llvm::json::Value ToJSON(Target &target, bool summary_only = false);
137137

138138
void SetLaunchOrAttachTime();
139139
void SetFirstPrivateStopTime();
@@ -171,9 +171,14 @@ class DebuggerStats {
171171
/// The single target to emit statistics for if non NULL, otherwise dump
172172
/// statistics only for the specified target.
173173
///
174+
/// \param summary_only
175+
/// If true, only report high level summary statistics without
176+
/// targets/modules/breakpoints etc.. details.
177+
///
174178
/// \return
175179
/// Returns a JSON value that contains all target metrics.
176-
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target);
180+
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target,
181+
bool summary_only = false);
177182

178183
protected:
179184
// Collecting stats can be set to true to collect stats that are expensive

lldb/include/lldb/Target/Target.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ class Target : public std::enable_shared_from_this<Target>,
15991599
///
16001600
/// \return
16011601
/// Returns a JSON value that contains all target metrics.
1602-
llvm::json::Value ReportStatistics();
1602+
llvm::json::Value ReportStatistics(bool summary_only = false);
16031603

16041604
TargetStats &GetStatistics() { return m_stats; }
16051605

lldb/source/API/SBTarget.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,18 @@ SBDebugger SBTarget::GetDebugger() const {
197197
return debugger;
198198
}
199199

200-
SBStructuredData SBTarget::GetStatistics() {
200+
SBStructuredData SBTarget::GetStatistics(bool summary_only) {
201201
LLDB_INSTRUMENT_VA(this);
202202

203203
SBStructuredData data;
204204
TargetSP target_sp(GetSP());
205205
if (!target_sp)
206206
return data;
207207
std::string json_str =
208-
llvm::formatv("{0:2}",
209-
DebuggerStats::ReportStatistics(target_sp->GetDebugger(),
210-
target_sp.get())).str();
208+
llvm::formatv(
209+
"{0:2}", DebuggerStats::ReportStatistics(
210+
target_sp->GetDebugger(), target_sp.get(), summary_only))
211+
.str();
211212
data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str));
212213
return data;
213214
}

lldb/source/Commands/CommandObjectStats.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ class CommandObjectStatsDump : public CommandObjectParsed {
7575
case 'a':
7676
m_all_targets = true;
7777
break;
78+
case 's':
79+
m_summary_only = true;
80+
break;
7881
default:
7982
llvm_unreachable("Unimplemented option");
8083
}
@@ -83,13 +86,15 @@ class CommandObjectStatsDump : public CommandObjectParsed {
8386

8487
void OptionParsingStarting(ExecutionContext *execution_context) override {
8588
m_all_targets = false;
89+
m_summary_only = false;
8690
}
8791

8892
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
8993
return llvm::ArrayRef(g_statistics_dump_options);
9094
}
9195

9296
bool m_all_targets = false;
97+
bool m_summary_only = false;
9398
};
9499

95100
public:
@@ -109,7 +114,8 @@ class CommandObjectStatsDump : public CommandObjectParsed {
109114
target = m_exe_ctx.GetTargetPtr();
110115

111116
result.AppendMessageWithFormatv(
112-
"{0:2}", DebuggerStats::ReportStatistics(GetDebugger(), target));
117+
"{0:2}", DebuggerStats::ReportStatistics(GetDebugger(), target,
118+
m_options.m_summary_only));
113119
result.SetStatus(eReturnStatusSuccessFinishResult);
114120
}
115121

lldb/source/Commands/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,4 +1412,7 @@ let Command = "trace schema" in {
14121412
let Command = "statistics dump" in {
14131413
def statistics_dump_all: Option<"all-targets", "a">, Group<1>,
14141414
Desc<"Include statistics for all targets.">;
1415+
def statistics_dump_summary: Option<"summary", "s">, Group<1>,
1416+
Desc<"Dump only high level summary statistics."
1417+
"Exclude targets, modules, breakpoints etc.. details.">;
14151418
}

lldb/source/Target/Statistics.cpp

Lines changed: 117 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "lldb/Core/Module.h"
1313
#include "lldb/Interpreter/CommandInterpreter.h"
1414
#include "lldb/Symbol/SymbolFile.h"
15+
#include "lldb/Target/DynamicLoader.h"
1516
#include "lldb/Target/Process.h"
1617
#include "lldb/Target/Target.h"
1718
#include "lldb/Target/UnixSignals.h"
@@ -74,7 +75,7 @@ json::Value ModuleStats::ToJSON() const {
7475

7576
if (!symfile_modules.empty()) {
7677
json::Array symfile_ids;
77-
for (const auto symfile_id: symfile_modules)
78+
for (const auto symfile_id : symfile_modules)
7879
symfile_ids.emplace_back(symfile_id);
7980
module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
8081
}
@@ -100,60 +101,91 @@ llvm::json::Value ConstStringStats::ToJSON() const {
100101
return obj;
101102
}
102103

103-
json::Value TargetStats::ToJSON(Target &target) {
104-
CollectStats(target);
104+
json::Value TargetStats::ToJSON(Target &target, bool summary_only) {
105+
json::Object target_metrics_json;
106+
ProcessSP process_sp = target.GetProcessSP();
107+
if (!summary_only) {
108+
CollectStats(target);
105109

106-
json::Array json_module_uuid_array;
107-
for (auto module_identifier : m_module_identifiers)
108-
json_module_uuid_array.emplace_back(module_identifier);
110+
json::Array json_module_uuid_array;
111+
for (auto module_identifier : m_module_identifiers)
112+
json_module_uuid_array.emplace_back(module_identifier);
109113

110-
json::Object target_metrics_json{
111-
{m_expr_eval.name, m_expr_eval.ToJSON()},
112-
{m_frame_var.name, m_frame_var.ToJSON()},
113-
{"moduleIdentifiers", std::move(json_module_uuid_array)}};
114+
target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
115+
target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
116+
target_metrics_json.try_emplace("moduleIdentifiers",
117+
std::move(json_module_uuid_array));
114118

115-
if (m_launch_or_attach_time && m_first_private_stop_time) {
116-
double elapsed_time =
117-
elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
118-
target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
119-
}
120-
if (m_launch_or_attach_time && m_first_public_stop_time) {
121-
double elapsed_time =
122-
elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
123-
target_metrics_json.try_emplace("firstStopTime", elapsed_time);
119+
if (m_launch_or_attach_time && m_first_private_stop_time) {
120+
double elapsed_time =
121+
elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
122+
target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
123+
}
124+
if (m_launch_or_attach_time && m_first_public_stop_time) {
125+
double elapsed_time =
126+
elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
127+
target_metrics_json.try_emplace("firstStopTime", elapsed_time);
128+
}
129+
target_metrics_json.try_emplace("targetCreateTime",
130+
m_create_time.get().count());
131+
132+
json::Array breakpoints_array;
133+
double totalBreakpointResolveTime = 0.0;
134+
// Rport both the normal breakpoint list and the internal breakpoint list.
135+
for (int i = 0; i < 2; ++i) {
136+
BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
137+
std::unique_lock<std::recursive_mutex> lock;
138+
breakpoints.GetListMutex(lock);
139+
size_t num_breakpoints = breakpoints.GetSize();
140+
for (size_t i = 0; i < num_breakpoints; i++) {
141+
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
142+
breakpoints_array.push_back(bp->GetStatistics());
143+
totalBreakpointResolveTime += bp->GetResolveTime().count();
144+
}
145+
}
146+
target_metrics_json.try_emplace("breakpoints",
147+
std::move(breakpoints_array));
148+
target_metrics_json.try_emplace("totalBreakpointResolveTime",
149+
totalBreakpointResolveTime);
150+
151+
if (process_sp) {
152+
UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
153+
if (unix_signals_sp)
154+
target_metrics_json.try_emplace(
155+
"signals", unix_signals_sp->GetHitCountStatistics());
156+
}
124157
}
125-
target_metrics_json.try_emplace("targetCreateTime",
126-
m_create_time.get().count());
127-
128-
json::Array breakpoints_array;
129-
double totalBreakpointResolveTime = 0.0;
130-
// Rport both the normal breakpoint list and the internal breakpoint list.
131-
for (int i = 0; i < 2; ++i) {
132-
BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
158+
159+
// Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
160+
// "shared-library-event".
161+
{
162+
uint32_t shared_library_event_breakpoint_hit_count = 0;
163+
// The "shared-library-event" is only found in the internal breakpoint list.
164+
BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
133165
std::unique_lock<std::recursive_mutex> lock;
134166
breakpoints.GetListMutex(lock);
135167
size_t num_breakpoints = breakpoints.GetSize();
136168
for (size_t i = 0; i < num_breakpoints; i++) {
137169
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
138-
breakpoints_array.push_back(bp->GetStatistics());
139-
totalBreakpointResolveTime += bp->GetResolveTime().count();
170+
if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
171+
shared_library_event_breakpoint_hit_count += bp->GetHitCount();
140172
}
173+
174+
target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
175+
shared_library_event_breakpoint_hit_count);
141176
}
142177

143-
ProcessSP process_sp = target.GetProcessSP();
144178
if (process_sp) {
145-
UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
146-
if (unix_signals_sp)
147-
target_metrics_json.try_emplace("signals",
148-
unix_signals_sp->GetHitCountStatistics());
149179
uint32_t stop_id = process_sp->GetStopID();
150180
target_metrics_json.try_emplace("stopCount", stop_id);
151-
}
152-
target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array));
153-
target_metrics_json.try_emplace("totalBreakpointResolveTime",
154-
totalBreakpointResolveTime);
155-
target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count);
156181

182+
llvm::StringRef dyld_plugin_name;
183+
if (process_sp->GetDynamicLoader())
184+
dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
185+
target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
186+
}
187+
target_metrics_json.try_emplace("sourceMapDeduceCount",
188+
m_source_map_deduce_count);
157189
return target_metrics_json;
158190
}
159191

@@ -185,7 +217,8 @@ void TargetStats::IncreaseSourceMapDeduceCount() {
185217
bool DebuggerStats::g_collecting_stats = false;
186218

187219
llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
188-
Target *target) {
220+
Target *target,
221+
bool summary_only) {
189222
json::Array json_targets;
190223
json::Array json_modules;
191224
double symtab_parse_time = 0.0;
@@ -197,12 +230,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
197230
uint32_t debug_index_loaded = 0;
198231
uint32_t debug_index_saved = 0;
199232
uint64_t debug_info_size = 0;
200-
if (target) {
201-
json_targets.emplace_back(target->ReportStatistics());
202-
} else {
203-
for (const auto &target : debugger.GetTargetList().Targets())
204-
json_targets.emplace_back(target->ReportStatistics());
205-
}
233+
206234
std::vector<ModuleStats> modules;
207235
std::lock_guard<std::recursive_mutex> guard(
208236
Module::GetAllocationModuleCollectionMutex());
@@ -215,15 +243,6 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
215243
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
216244
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
217245
ModuleStats module_stat;
218-
module_stat.identifier = (intptr_t)module;
219-
module_stat.path = module->GetFileSpec().GetPath();
220-
if (ConstString object_name = module->GetObjectName()) {
221-
module_stat.path.append(1, '(');
222-
module_stat.path.append(object_name.GetStringRef().str());
223-
module_stat.path.append(1, ')');
224-
}
225-
module_stat.uuid = module->GetUUID().GetAsString();
226-
module_stat.triple = module->GetArchitecture().GetTriple().str();
227246
module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
228247
module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
229248
Symtab *symtab = module->GetSymtab();
@@ -237,13 +256,14 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
237256
}
238257
SymbolFile *sym_file = module->GetSymbolFile();
239258
if (sym_file) {
240-
241-
if (sym_file->GetObjectFile() != module->GetObjectFile())
242-
module_stat.symfile_path =
243-
sym_file->GetObjectFile()->GetFileSpec().GetPath();
244-
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
245-
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
246-
module_stat.debug_info_size = sym_file->GetDebugInfoSize();
259+
if (!summary_only) {
260+
if (sym_file->GetObjectFile() != module->GetObjectFile())
261+
module_stat.symfile_path =
262+
sym_file->GetObjectFile()->GetFileSpec().GetPath();
263+
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
264+
for (const auto &symbol_module : symbol_modules.Modules())
265+
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
266+
}
247267
module_stat.debug_info_index_loaded_from_cache =
248268
sym_file->GetDebugInfoIndexWasLoadedFromCache();
249269
if (module_stat.debug_info_index_loaded_from_cache)
@@ -252,9 +272,9 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
252272
sym_file->GetDebugInfoIndexWasSavedToCache();
253273
if (module_stat.debug_info_index_saved_to_cache)
254274
++debug_index_saved;
255-
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
256-
for (const auto &symbol_module: symbol_modules.Modules())
257-
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
275+
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
276+
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
277+
module_stat.debug_info_size = sym_file->GetDebugInfoSize();
258278
module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
259279
if (module_stat.symtab_stripped)
260280
++num_stripped_modules;
@@ -284,21 +304,21 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
284304
if (module_stat.debug_info_had_incomplete_types)
285305
++num_modules_with_incomplete_types;
286306

287-
json_modules.emplace_back(module_stat.ToJSON());
307+
if (!summary_only) {
308+
module_stat.identifier = (intptr_t)module;
309+
module_stat.path = module->GetFileSpec().GetPath();
310+
if (ConstString object_name = module->GetObjectName()) {
311+
module_stat.path.append(1, '(');
312+
module_stat.path.append(object_name.GetStringRef().str());
313+
module_stat.path.append(1, ')');
314+
}
315+
module_stat.uuid = module->GetUUID().GetAsString();
316+
module_stat.triple = module->GetArchitecture().GetTriple().str();
317+
json_modules.emplace_back(module_stat.ToJSON());
318+
}
288319
}
289320

290-
ConstStringStats const_string_stats;
291-
json::Object json_memory{
292-
{"strings", const_string_stats.ToJSON()},
293-
};
294-
295-
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
296-
297321
json::Object global_stats{
298-
{"targets", std::move(json_targets)},
299-
{"modules", std::move(json_modules)},
300-
{"memory", std::move(json_memory)},
301-
{"commands", std::move(cmd_stats)},
302322
{"totalSymbolTableParseTime", symtab_parse_time},
303323
{"totalSymbolTableIndexTime", symtab_index_time},
304324
{"totalSymbolTablesLoadedFromCache", symtabs_loaded},
@@ -316,5 +336,25 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
316336
{"totalDebugInfoEnabled", num_debug_info_enabled_modules},
317337
{"totalSymbolTableStripped", num_stripped_modules},
318338
};
339+
340+
if (target) {
341+
json_targets.emplace_back(target->ReportStatistics(summary_only));
342+
} else {
343+
for (const auto &target : debugger.GetTargetList().Targets())
344+
json_targets.emplace_back(target->ReportStatistics(summary_only));
345+
}
346+
global_stats.try_emplace("targets", std::move(json_targets));
347+
348+
if (!summary_only) {
349+
ConstStringStats const_string_stats;
350+
json::Object json_memory{
351+
{"strings", const_string_stats.ToJSON()},
352+
};
353+
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
354+
global_stats.try_emplace("modules", std::move(json_modules));
355+
global_stats.try_emplace("memory", std::move(json_memory));
356+
global_stats.try_emplace("commands", std::move(cmd_stats));
357+
}
358+
319359
return std::move(global_stats);
320360
}

0 commit comments

Comments
 (0)