Support statistics dump summary only mode (#80745)
Add a new --summary option to statistics dump command so that it is much more light weight than the full version. Introduce a new SBStatisticsOptions API setting the verbosity of statistics dump. [PR #80218](https://github.com/llvm/llvm-project/pull/80218#discussion_r1473639878)
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
#include "lldb/API/SBScriptObject.h"
|
||||
#include "lldb/API/SBSection.h"
|
||||
#include "lldb/API/SBSourceManager.h"
|
||||
#include "lldb/API/SBStatisticsOptions.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBStringList.h"
|
||||
#include "lldb/API/SBStructuredData.h"
|
||||
|
||||
8
lldb/bindings/interface/SBStatisticsOptionsDocStrings.i
Normal file
8
lldb/bindings/interface/SBStatisticsOptionsDocStrings.i
Normal file
@@ -0,0 +1,8 @@
|
||||
%feature("docstring",
|
||||
"A container for options to use when dumping statistics."
|
||||
) lldb::SBStatisticsOptions;
|
||||
|
||||
%feature("docstring", "Sets whether the statistics should only dump a summary."
|
||||
) lldb::SBStatisticsOptions::SetSummaryOnly;
|
||||
%feature("docstring", "Gets whether the statistics only dump a summary."
|
||||
) lldb::SBStatisticsOptions::GetSummaryOnly;
|
||||
@@ -56,6 +56,7 @@
|
||||
%include "./interface/SBReproducerDocstrings.i"
|
||||
%include "./interface/SBSectionDocstrings.i"
|
||||
%include "./interface/SBSourceManagerDocstrings.i"
|
||||
%include "./interface/SBStatisticsOptionsDocstrings.i"
|
||||
%include "./interface/SBStreamDocstrings.i"
|
||||
%include "./interface/SBStringListDocstrings.i"
|
||||
%include "./interface/SBStructuredDataDocstrings.i"
|
||||
@@ -131,6 +132,7 @@
|
||||
%include "lldb/API/SBScriptObject.h"
|
||||
%include "lldb/API/SBSection.h"
|
||||
%include "lldb/API/SBSourceManager.h"
|
||||
%include "lldb/API/SBStatisticsOptions.h"
|
||||
%include "lldb/API/SBStream.h"
|
||||
%include "lldb/API/SBStringList.h"
|
||||
%include "lldb/API/SBStructuredData.h"
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "lldb/API/SBReproducer.h"
|
||||
#include "lldb/API/SBSection.h"
|
||||
#include "lldb/API/SBSourceManager.h"
|
||||
#include "lldb/API/SBStatisticsOptions.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBStringList.h"
|
||||
#include "lldb/API/SBStructuredData.h"
|
||||
|
||||
@@ -99,6 +99,7 @@ class LLDB_API SBReproducer;
|
||||
class LLDB_API SBScriptObject;
|
||||
class LLDB_API SBSection;
|
||||
class LLDB_API SBSourceManager;
|
||||
class LLDB_API SBStatisticsOptions;
|
||||
class LLDB_API SBStream;
|
||||
class LLDB_API SBStringList;
|
||||
class LLDB_API SBStructuredData;
|
||||
|
||||
36
lldb/include/lldb/API/SBStatisticsOptions.h
Normal file
36
lldb/include/lldb/API/SBStatisticsOptions.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//===-- SBStatisticsOptions.h -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_API_SBSTATISTICSOPTIONS_H
|
||||
#define LLDB_API_SBSTATISTICSOPTIONS_H
|
||||
|
||||
#include "lldb/API/SBDefines.h"
|
||||
|
||||
namespace lldb {
|
||||
|
||||
/// This class handles the verbosity when dumping statistics
|
||||
class LLDB_API SBStatisticsOptions {
|
||||
public:
|
||||
SBStatisticsOptions();
|
||||
SBStatisticsOptions(const lldb::SBStatisticsOptions &rhs);
|
||||
~SBStatisticsOptions();
|
||||
|
||||
const SBStatisticsOptions &operator=(const lldb::SBStatisticsOptions &rhs);
|
||||
|
||||
void SetSummaryOnly(bool b);
|
||||
bool GetSummaryOnly();
|
||||
|
||||
protected:
|
||||
friend class SBTarget;
|
||||
const lldb_private::StatisticsOptions &ref() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<lldb_private::StatisticsOptions> m_opaque_up;
|
||||
};
|
||||
} // namespace lldb
|
||||
#endif // LLDB_API_SBSTATISTICSOPTIONS_H
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "lldb/API/SBFileSpec.h"
|
||||
#include "lldb/API/SBFileSpecList.h"
|
||||
#include "lldb/API/SBLaunchInfo.h"
|
||||
#include "lldb/API/SBStatisticsOptions.h"
|
||||
#include "lldb/API/SBSymbolContextList.h"
|
||||
#include "lldb/API/SBType.h"
|
||||
#include "lldb/API/SBValue.h"
|
||||
@@ -90,6 +91,15 @@ public:
|
||||
/// A SBStructuredData with the statistics collected.
|
||||
lldb::SBStructuredData GetStatistics();
|
||||
|
||||
/// Returns a dump of the collected statistics.
|
||||
///
|
||||
/// \param[in] options
|
||||
/// An objects object that contains all options for the statistics dumping.
|
||||
///
|
||||
/// \return
|
||||
/// A SBStructuredData with the statistics collected.
|
||||
lldb::SBStructuredData GetStatistics(SBStatisticsOptions options);
|
||||
|
||||
/// Return the platform object associated with the target.
|
||||
///
|
||||
/// After return, the platform object should be checked for
|
||||
|
||||
@@ -130,10 +130,15 @@ struct ConstStringStats {
|
||||
ConstString::MemoryStats stats = ConstString::GetMemoryStats();
|
||||
};
|
||||
|
||||
struct StatisticsOptions {
|
||||
bool summary_only = false;
|
||||
};
|
||||
|
||||
/// A class that represents statistics for a since lldb_private::Target.
|
||||
class TargetStats {
|
||||
public:
|
||||
llvm::json::Value ToJSON(Target &target);
|
||||
llvm::json::Value ToJSON(Target &target,
|
||||
const lldb_private::StatisticsOptions &options);
|
||||
|
||||
void SetLaunchOrAttachTime();
|
||||
void SetFirstPrivateStopTime();
|
||||
@@ -171,9 +176,15 @@ public:
|
||||
/// The single target to emit statistics for if non NULL, otherwise dump
|
||||
/// statistics only for the specified target.
|
||||
///
|
||||
/// \param summary_only
|
||||
/// If true, only report high level summary statistics without
|
||||
/// targets/modules/breakpoints etc.. details.
|
||||
///
|
||||
/// \return
|
||||
/// Returns a JSON value that contains all target metrics.
|
||||
static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target);
|
||||
static llvm::json::Value
|
||||
ReportStatistics(Debugger &debugger, Target *target,
|
||||
const lldb_private::StatisticsOptions &options);
|
||||
|
||||
protected:
|
||||
// Collecting stats can be set to true to collect stats that are expensive
|
||||
|
||||
@@ -1599,7 +1599,8 @@ public:
|
||||
///
|
||||
/// \return
|
||||
/// Returns a JSON value that contains all target metrics.
|
||||
llvm::json::Value ReportStatistics();
|
||||
llvm::json::Value
|
||||
ReportStatistics(const lldb_private::StatisticsOptions &options);
|
||||
|
||||
TargetStats &GetStatistics() { return m_stats; }
|
||||
|
||||
|
||||
@@ -298,6 +298,7 @@ struct CompilerContext;
|
||||
struct LineEntry;
|
||||
struct PropertyDefinition;
|
||||
struct ScriptSummaryFormat;
|
||||
struct StatisticsOptions;
|
||||
struct StringSummaryFormat;
|
||||
template <unsigned N> class StreamBuffer;
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
|
||||
SBScriptObject.cpp
|
||||
SBSection.cpp
|
||||
SBSourceManager.cpp
|
||||
SBStatisticsOptions.cpp
|
||||
SBStream.cpp
|
||||
SBStringList.cpp
|
||||
SBStructuredData.cpp
|
||||
|
||||
49
lldb/source/API/SBStatisticsOptions.cpp
Normal file
49
lldb/source/API/SBStatisticsOptions.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//===-- SBStatisticsOptions.cpp -------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/API/SBStatisticsOptions.h"
|
||||
#include "lldb/Target/Statistics.h"
|
||||
#include "lldb/Utility/Instrumentation.h"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
SBStatisticsOptions::SBStatisticsOptions()
|
||||
: m_opaque_up(new StatisticsOptions()) {
|
||||
LLDB_INSTRUMENT_VA(this);
|
||||
m_opaque_up->summary_only = false;
|
||||
}
|
||||
|
||||
SBStatisticsOptions::SBStatisticsOptions(const SBStatisticsOptions &rhs) {
|
||||
LLDB_INSTRUMENT_VA(this, rhs);
|
||||
|
||||
m_opaque_up = clone(rhs.m_opaque_up);
|
||||
}
|
||||
|
||||
SBStatisticsOptions::~SBStatisticsOptions() = default;
|
||||
|
||||
const SBStatisticsOptions &
|
||||
SBStatisticsOptions::operator=(const SBStatisticsOptions &rhs) {
|
||||
LLDB_INSTRUMENT_VA(this, rhs);
|
||||
|
||||
if (this != &rhs)
|
||||
m_opaque_up = clone(rhs.m_opaque_up);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SBStatisticsOptions::SetSummaryOnly(bool b) {
|
||||
m_opaque_up->summary_only = b;
|
||||
}
|
||||
|
||||
bool SBStatisticsOptions::GetSummaryOnly() { return m_opaque_up->summary_only; }
|
||||
|
||||
const lldb_private::StatisticsOptions &SBStatisticsOptions::ref() const {
|
||||
return *m_opaque_up;
|
||||
}
|
||||
@@ -199,15 +199,22 @@ SBDebugger SBTarget::GetDebugger() const {
|
||||
|
||||
SBStructuredData SBTarget::GetStatistics() {
|
||||
LLDB_INSTRUMENT_VA(this);
|
||||
SBStatisticsOptions options;
|
||||
return GetStatistics(options);
|
||||
}
|
||||
|
||||
SBStructuredData SBTarget::GetStatistics(SBStatisticsOptions options) {
|
||||
LLDB_INSTRUMENT_VA(this);
|
||||
|
||||
SBStructuredData data;
|
||||
TargetSP target_sp(GetSP());
|
||||
if (!target_sp)
|
||||
return data;
|
||||
std::string json_str =
|
||||
llvm::formatv("{0:2}",
|
||||
DebuggerStats::ReportStatistics(target_sp->GetDebugger(),
|
||||
target_sp.get())).str();
|
||||
llvm::formatv("{0:2}", DebuggerStats::ReportStatistics(
|
||||
target_sp->GetDebugger(), target_sp.get(),
|
||||
options.ref()))
|
||||
.str();
|
||||
data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str));
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,9 @@ class CommandObjectStatsDump : public CommandObjectParsed {
|
||||
case 'a':
|
||||
m_all_targets = true;
|
||||
break;
|
||||
case 's':
|
||||
m_stats_options.summary_only = true;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unimplemented option");
|
||||
}
|
||||
@@ -83,13 +86,17 @@ class CommandObjectStatsDump : public CommandObjectParsed {
|
||||
|
||||
void OptionParsingStarting(ExecutionContext *execution_context) override {
|
||||
m_all_targets = false;
|
||||
m_stats_options = StatisticsOptions();
|
||||
}
|
||||
|
||||
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
|
||||
return llvm::ArrayRef(g_statistics_dump_options);
|
||||
}
|
||||
|
||||
const StatisticsOptions &GetStatisticsOptions() { return m_stats_options; }
|
||||
|
||||
bool m_all_targets = false;
|
||||
StatisticsOptions m_stats_options = StatisticsOptions();
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -109,7 +116,8 @@ protected:
|
||||
target = m_exe_ctx.GetTargetPtr();
|
||||
|
||||
result.AppendMessageWithFormatv(
|
||||
"{0:2}", DebuggerStats::ReportStatistics(GetDebugger(), target));
|
||||
"{0:2}", DebuggerStats::ReportStatistics(
|
||||
GetDebugger(), target, m_options.GetStatisticsOptions()));
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -1412,4 +1412,7 @@ let Command = "trace schema" in {
|
||||
let Command = "statistics dump" in {
|
||||
def statistics_dump_all: Option<"all-targets", "a">, Group<1>,
|
||||
Desc<"Include statistics for all targets.">;
|
||||
def statistics_dump_summary: Option<"summary", "s">, Group<1>,
|
||||
Desc<"Dump only high-level summary statistics."
|
||||
"Exclude targets, modules, breakpoints etc... details.">;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Symbol/SymbolFile.h"
|
||||
#include "lldb/Target/DynamicLoader.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/UnixSignals.h"
|
||||
@@ -100,60 +101,94 @@ llvm::json::Value ConstStringStats::ToJSON() const {
|
||||
return obj;
|
||||
}
|
||||
|
||||
json::Value TargetStats::ToJSON(Target &target) {
|
||||
CollectStats(target);
|
||||
json::Value
|
||||
TargetStats::ToJSON(Target &target,
|
||||
const lldb_private::StatisticsOptions &options) {
|
||||
json::Object target_metrics_json;
|
||||
ProcessSP process_sp = target.GetProcessSP();
|
||||
const bool summary_only = options.summary_only;
|
||||
if (!summary_only) {
|
||||
CollectStats(target);
|
||||
|
||||
json::Array json_module_uuid_array;
|
||||
for (auto module_identifier : m_module_identifiers)
|
||||
json_module_uuid_array.emplace_back(module_identifier);
|
||||
json::Array json_module_uuid_array;
|
||||
for (auto module_identifier : m_module_identifiers)
|
||||
json_module_uuid_array.emplace_back(module_identifier);
|
||||
|
||||
json::Object target_metrics_json{
|
||||
{m_expr_eval.name, m_expr_eval.ToJSON()},
|
||||
{m_frame_var.name, m_frame_var.ToJSON()},
|
||||
{"moduleIdentifiers", std::move(json_module_uuid_array)}};
|
||||
target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
|
||||
target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
|
||||
target_metrics_json.try_emplace("moduleIdentifiers",
|
||||
std::move(json_module_uuid_array));
|
||||
|
||||
if (m_launch_or_attach_time && m_first_private_stop_time) {
|
||||
double elapsed_time =
|
||||
elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
|
||||
target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
|
||||
if (m_launch_or_attach_time && m_first_private_stop_time) {
|
||||
double elapsed_time =
|
||||
elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
|
||||
target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
|
||||
}
|
||||
if (m_launch_or_attach_time && m_first_public_stop_time) {
|
||||
double elapsed_time =
|
||||
elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
|
||||
target_metrics_json.try_emplace("firstStopTime", elapsed_time);
|
||||
}
|
||||
target_metrics_json.try_emplace("targetCreateTime",
|
||||
m_create_time.get().count());
|
||||
|
||||
json::Array breakpoints_array;
|
||||
double totalBreakpointResolveTime = 0.0;
|
||||
// Report both the normal breakpoint list and the internal breakpoint list.
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
|
||||
std::unique_lock<std::recursive_mutex> lock;
|
||||
breakpoints.GetListMutex(lock);
|
||||
size_t num_breakpoints = breakpoints.GetSize();
|
||||
for (size_t i = 0; i < num_breakpoints; i++) {
|
||||
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
|
||||
breakpoints_array.push_back(bp->GetStatistics());
|
||||
totalBreakpointResolveTime += bp->GetResolveTime().count();
|
||||
}
|
||||
}
|
||||
target_metrics_json.try_emplace("breakpoints",
|
||||
std::move(breakpoints_array));
|
||||
target_metrics_json.try_emplace("totalBreakpointResolveTime",
|
||||
totalBreakpointResolveTime);
|
||||
|
||||
if (process_sp) {
|
||||
UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
|
||||
if (unix_signals_sp)
|
||||
target_metrics_json.try_emplace(
|
||||
"signals", unix_signals_sp->GetHitCountStatistics());
|
||||
}
|
||||
}
|
||||
if (m_launch_or_attach_time && m_first_public_stop_time) {
|
||||
double elapsed_time =
|
||||
elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
|
||||
target_metrics_json.try_emplace("firstStopTime", elapsed_time);
|
||||
}
|
||||
target_metrics_json.try_emplace("targetCreateTime",
|
||||
m_create_time.get().count());
|
||||
|
||||
json::Array breakpoints_array;
|
||||
double totalBreakpointResolveTime = 0.0;
|
||||
// Rport both the normal breakpoint list and the internal breakpoint list.
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
|
||||
// Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
|
||||
// "shared-library-event".
|
||||
{
|
||||
uint32_t shared_library_event_breakpoint_hit_count = 0;
|
||||
// The "shared-library-event" is only found in the internal breakpoint list.
|
||||
BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
|
||||
std::unique_lock<std::recursive_mutex> lock;
|
||||
breakpoints.GetListMutex(lock);
|
||||
size_t num_breakpoints = breakpoints.GetSize();
|
||||
for (size_t i = 0; i < num_breakpoints; i++) {
|
||||
Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
|
||||
breakpoints_array.push_back(bp->GetStatistics());
|
||||
totalBreakpointResolveTime += bp->GetResolveTime().count();
|
||||
if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
|
||||
shared_library_event_breakpoint_hit_count += bp->GetHitCount();
|
||||
}
|
||||
|
||||
target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
|
||||
shared_library_event_breakpoint_hit_count);
|
||||
}
|
||||
|
||||
ProcessSP process_sp = target.GetProcessSP();
|
||||
if (process_sp) {
|
||||
UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
|
||||
if (unix_signals_sp)
|
||||
target_metrics_json.try_emplace("signals",
|
||||
unix_signals_sp->GetHitCountStatistics());
|
||||
uint32_t stop_id = process_sp->GetStopID();
|
||||
target_metrics_json.try_emplace("stopCount", stop_id);
|
||||
}
|
||||
target_metrics_json.try_emplace("breakpoints", std::move(breakpoints_array));
|
||||
target_metrics_json.try_emplace("totalBreakpointResolveTime",
|
||||
totalBreakpointResolveTime);
|
||||
target_metrics_json.try_emplace("sourceMapDeduceCount", m_source_map_deduce_count);
|
||||
|
||||
llvm::StringRef dyld_plugin_name;
|
||||
if (process_sp->GetDynamicLoader())
|
||||
dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
|
||||
target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
|
||||
}
|
||||
target_metrics_json.try_emplace("sourceMapDeduceCount",
|
||||
m_source_map_deduce_count);
|
||||
return target_metrics_json;
|
||||
}
|
||||
|
||||
@@ -184,8 +219,12 @@ void TargetStats::IncreaseSourceMapDeduceCount() {
|
||||
|
||||
bool DebuggerStats::g_collecting_stats = false;
|
||||
|
||||
llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
Target *target) {
|
||||
llvm::json::Value DebuggerStats::ReportStatistics(
|
||||
Debugger &debugger, Target *target,
|
||||
const lldb_private::StatisticsOptions &options) {
|
||||
|
||||
const bool summary_only = options.summary_only;
|
||||
|
||||
json::Array json_targets;
|
||||
json::Array json_modules;
|
||||
double symtab_parse_time = 0.0;
|
||||
@@ -197,12 +236,7 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
uint32_t debug_index_loaded = 0;
|
||||
uint32_t debug_index_saved = 0;
|
||||
uint64_t debug_info_size = 0;
|
||||
if (target) {
|
||||
json_targets.emplace_back(target->ReportStatistics());
|
||||
} else {
|
||||
for (const auto &target : debugger.GetTargetList().Targets())
|
||||
json_targets.emplace_back(target->ReportStatistics());
|
||||
}
|
||||
|
||||
std::vector<ModuleStats> modules;
|
||||
std::lock_guard<std::recursive_mutex> guard(
|
||||
Module::GetAllocationModuleCollectionMutex());
|
||||
@@ -215,15 +249,6 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
|
||||
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
|
||||
ModuleStats module_stat;
|
||||
module_stat.identifier = (intptr_t)module;
|
||||
module_stat.path = module->GetFileSpec().GetPath();
|
||||
if (ConstString object_name = module->GetObjectName()) {
|
||||
module_stat.path.append(1, '(');
|
||||
module_stat.path.append(object_name.GetStringRef().str());
|
||||
module_stat.path.append(1, ')');
|
||||
}
|
||||
module_stat.uuid = module->GetUUID().GetAsString();
|
||||
module_stat.triple = module->GetArchitecture().GetTriple().str();
|
||||
module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
|
||||
module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
|
||||
Symtab *symtab = module->GetSymtab();
|
||||
@@ -237,13 +262,14 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
}
|
||||
SymbolFile *sym_file = module->GetSymbolFile();
|
||||
if (sym_file) {
|
||||
|
||||
if (sym_file->GetObjectFile() != module->GetObjectFile())
|
||||
module_stat.symfile_path =
|
||||
sym_file->GetObjectFile()->GetFileSpec().GetPath();
|
||||
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
|
||||
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
|
||||
module_stat.debug_info_size = sym_file->GetDebugInfoSize();
|
||||
if (!summary_only) {
|
||||
if (sym_file->GetObjectFile() != module->GetObjectFile())
|
||||
module_stat.symfile_path =
|
||||
sym_file->GetObjectFile()->GetFileSpec().GetPath();
|
||||
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
|
||||
for (const auto &symbol_module : symbol_modules.Modules())
|
||||
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
|
||||
}
|
||||
module_stat.debug_info_index_loaded_from_cache =
|
||||
sym_file->GetDebugInfoIndexWasLoadedFromCache();
|
||||
if (module_stat.debug_info_index_loaded_from_cache)
|
||||
@@ -252,9 +278,9 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
sym_file->GetDebugInfoIndexWasSavedToCache();
|
||||
if (module_stat.debug_info_index_saved_to_cache)
|
||||
++debug_index_saved;
|
||||
ModuleList symbol_modules = sym_file->GetDebugInfoModules();
|
||||
for (const auto &symbol_module: symbol_modules.Modules())
|
||||
module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
|
||||
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
|
||||
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
|
||||
module_stat.debug_info_size = sym_file->GetDebugInfoSize();
|
||||
module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
|
||||
if (module_stat.symtab_stripped)
|
||||
++num_stripped_modules;
|
||||
@@ -284,21 +310,21 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
if (module_stat.debug_info_had_incomplete_types)
|
||||
++num_modules_with_incomplete_types;
|
||||
|
||||
json_modules.emplace_back(module_stat.ToJSON());
|
||||
if (!summary_only) {
|
||||
module_stat.identifier = (intptr_t)module;
|
||||
module_stat.path = module->GetFileSpec().GetPath();
|
||||
if (ConstString object_name = module->GetObjectName()) {
|
||||
module_stat.path.append(1, '(');
|
||||
module_stat.path.append(object_name.GetStringRef().str());
|
||||
module_stat.path.append(1, ')');
|
||||
}
|
||||
module_stat.uuid = module->GetUUID().GetAsString();
|
||||
module_stat.triple = module->GetArchitecture().GetTriple().str();
|
||||
json_modules.emplace_back(module_stat.ToJSON());
|
||||
}
|
||||
}
|
||||
|
||||
ConstStringStats const_string_stats;
|
||||
json::Object json_memory{
|
||||
{"strings", const_string_stats.ToJSON()},
|
||||
};
|
||||
|
||||
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
|
||||
|
||||
json::Object global_stats{
|
||||
{"targets", std::move(json_targets)},
|
||||
{"modules", std::move(json_modules)},
|
||||
{"memory", std::move(json_memory)},
|
||||
{"commands", std::move(cmd_stats)},
|
||||
{"totalSymbolTableParseTime", symtab_parse_time},
|
||||
{"totalSymbolTableIndexTime", symtab_index_time},
|
||||
{"totalSymbolTablesLoadedFromCache", symtabs_loaded},
|
||||
@@ -316,5 +342,25 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
|
||||
{"totalDebugInfoEnabled", num_debug_info_enabled_modules},
|
||||
{"totalSymbolTableStripped", num_stripped_modules},
|
||||
};
|
||||
|
||||
if (target) {
|
||||
json_targets.emplace_back(target->ReportStatistics(options));
|
||||
} else {
|
||||
for (const auto &target : debugger.GetTargetList().Targets())
|
||||
json_targets.emplace_back(target->ReportStatistics(options));
|
||||
}
|
||||
global_stats.try_emplace("targets", std::move(json_targets));
|
||||
|
||||
if (!summary_only) {
|
||||
ConstStringStats const_string_stats;
|
||||
json::Object json_memory{
|
||||
{"strings", const_string_stats.ToJSON()},
|
||||
};
|
||||
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
|
||||
global_stats.try_emplace("modules", std::move(json_modules));
|
||||
global_stats.try_emplace("memory", std::move(json_memory));
|
||||
global_stats.try_emplace("commands", std::move(cmd_stats));
|
||||
}
|
||||
|
||||
return std::move(global_stats);
|
||||
}
|
||||
|
||||
@@ -4962,4 +4962,7 @@ std::recursive_mutex &Target::GetAPIMutex() {
|
||||
}
|
||||
|
||||
/// Get metrics associated with this target in JSON format.
|
||||
llvm::json::Value Target::ReportStatistics() { return m_stats.ToJSON(*this); }
|
||||
llvm::json::Value
|
||||
Target::ReportStatistics(const lldb_private::StatisticsOptions &options) {
|
||||
return m_stats.ToJSON(*this, options);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@ class TestStatsAPI(TestBase):
|
||||
"""
|
||||
self.build()
|
||||
exe = self.getBuildArtifact("a.out")
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
# Launch a process and break
|
||||
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||
self, "break here", lldb.SBFileSpec("main.c")
|
||||
)
|
||||
|
||||
# Test enabling/disabling stats
|
||||
self.assertFalse(target.GetCollectingStats())
|
||||
@@ -74,6 +77,24 @@ class TestStatsAPI(TestBase):
|
||||
'Make sure the "failures" key in in "frameVariable" dictionary"',
|
||||
)
|
||||
|
||||
# Test statistics summary.
|
||||
stats_options = lldb.SBStatisticsOptions()
|
||||
stats_options.SetSummaryOnly(True)
|
||||
stats_summary = target.GetStatistics(stats_options)
|
||||
stream_summary = lldb.SBStream()
|
||||
stats_summary.GetAsJSON(stream_summary)
|
||||
debug_stats_summary = json.loads(stream_summary.GetData())
|
||||
self.assertNotIn("modules", debug_stats_summary)
|
||||
self.assertNotIn("memory", debug_stats_summary)
|
||||
self.assertNotIn("commands", debug_stats_summary)
|
||||
|
||||
# Summary values should be the same as in full statistics.
|
||||
# Except the parse time on Mac OS X is not deterministic.
|
||||
for key, value in debug_stats_summary.items():
|
||||
self.assertIn(key, debug_stats)
|
||||
if key != "targets" and not key.endswith("Time"):
|
||||
self.assertEqual(debug_stats[key], value)
|
||||
|
||||
def test_command_stats_api(self):
|
||||
"""
|
||||
Test GetCommandInterpreter::GetStatistics() API.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
int main(void) {
|
||||
return 0;
|
||||
return 0; // break here
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user