2021-10-20 14:49:09 -07:00
|
|
|
//===-- Statistics.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/Target/Statistics.h"
|
|
|
|
|
|
|
|
|
|
#include "lldb/Core/Debugger.h"
|
|
|
|
|
#include "lldb/Core/Module.h"
|
2024-02-05 13:17:29 -08:00
|
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
#include "lldb/Symbol/SymbolFile.h"
|
2024-02-06 19:47:34 -05:00
|
|
|
#include "lldb/Target/DynamicLoader.h"
|
2021-10-27 18:33:17 -07:00
|
|
|
#include "lldb/Target/Process.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
#include "lldb/Target/Target.h"
|
2021-10-27 18:33:17 -07:00
|
|
|
#include "lldb/Target/UnixSignals.h"
|
2024-06-03 13:52:03 -07:00
|
|
|
#include "lldb/Utility/StructuredData.h"
|
2021-10-20 14:49:09 -07:00
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
|
|
|
|
|
const std::string &str) {
|
|
|
|
|
if (str.empty())
|
|
|
|
|
return;
|
|
|
|
|
if (LLVM_LIKELY(llvm::json::isUTF8(str)))
|
|
|
|
|
obj.try_emplace(key, str);
|
|
|
|
|
else
|
|
|
|
|
obj.try_emplace(key, llvm::json::fixUTF8(str));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
json::Value StatsSuccessFail::ToJSON() const {
|
|
|
|
|
return json::Object{{"successes", successes}, {"failures", failures}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
|
2022-01-17 15:04:30 +01:00
|
|
|
StatsDuration::Duration elapsed =
|
|
|
|
|
end.time_since_epoch() - start.time_since_epoch();
|
2021-10-20 14:49:09 -07:00
|
|
|
return elapsed.count();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
void TargetStats::CollectStats(Target &target) {
|
|
|
|
|
m_module_identifiers.clear();
|
|
|
|
|
for (ModuleSP module_sp : target.GetImages().Modules())
|
|
|
|
|
m_module_identifiers.emplace_back((intptr_t)module_sp.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json::Value ModuleStats::ToJSON() const {
|
|
|
|
|
json::Object module;
|
|
|
|
|
EmplaceSafeString(module, "path", path);
|
|
|
|
|
EmplaceSafeString(module, "uuid", uuid);
|
|
|
|
|
EmplaceSafeString(module, "triple", triple);
|
|
|
|
|
module.try_emplace("identifier", identifier);
|
|
|
|
|
module.try_emplace("symbolTableParseTime", symtab_parse_time);
|
|
|
|
|
module.try_emplace("symbolTableIndexTime", symtab_index_time);
|
2021-12-28 10:49:59 -08:00
|
|
|
module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
|
|
|
|
|
module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
|
2021-10-25 18:03:06 -07:00
|
|
|
module.try_emplace("debugInfoParseTime", debug_parse_time);
|
|
|
|
|
module.try_emplace("debugInfoIndexTime", debug_index_time);
|
|
|
|
|
module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
|
2021-12-28 10:49:59 -08:00
|
|
|
module.try_emplace("debugInfoIndexLoadedFromCache",
|
|
|
|
|
debug_info_index_loaded_from_cache);
|
|
|
|
|
module.try_emplace("debugInfoIndexSavedToCache",
|
|
|
|
|
debug_info_index_saved_to_cache);
|
2022-04-20 07:30:53 -07:00
|
|
|
module.try_emplace("debugInfoEnabled", debug_info_enabled);
|
2022-09-22 17:54:06 -07:00
|
|
|
module.try_emplace("debugInfoHadVariableErrors",
|
|
|
|
|
debug_info_had_variable_errors);
|
2022-11-23 20:28:03 -08:00
|
|
|
module.try_emplace("debugInfoHadIncompleteTypes",
|
|
|
|
|
debug_info_had_incomplete_types);
|
2022-04-20 07:30:53 -07:00
|
|
|
module.try_emplace("symbolTableStripped", symtab_stripped);
|
Fix a double debug info size counting in top level stats for "statistics dump".
This mainly affects Darwin targets (macOS, iOS, tvOS and watchOS) when these targets don't use dSYM files and the debug info was in the .o files. All modules, including the .o files that are loaded by the debug maps, were in the global module list. This was great because it allows us to see each .o file and how much it contributes. There were virtual functions on the SymbolFile class to fetch the symtab/debug info parse and index times, and also the total debug info size. So the main executable would add all of the .o file's stats together and report them as its own data. Then the "totalDebugInfoSize" and many other "totalXXX" top level totals were all being added together. This stems from the fact that my original patch only emitted the modules for a target at the start of the patch, but as comments from the reviews came in, we switched to emitting all of the modules from the global module list.
So this patch fixes it so when we have a SymbolFileDWARFDebugMap that loads .o files, the main executable will have no debug info size or symtab/debug info parse/index times, but each .o file will have its own data as a separate module. Also, to be able to tell when/if we have a dSYM file I have added a "symbolFilePath" if the SymbolFile for the main modules path doesn't match that of the main executable. We also include a "symbolFileModuleIdentifiers" key in each module if the module does have multiple lldb_private::Module objects that contain debug info so that you can track down the information for a module and add up the contributions of all of the .o files.
Tests were added that are labeled with @skipUnlessDarwin and @no_debug_info_test that test all of this functionality so it doesn't regress.
For a module with a dSYM file, we can see the "symbolFilePath" is included:
```
"modules": [
{
"debugInfoByteSize": 1070,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 0,
"identifier": 4873280600,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_dsym_binary_has_symfile_in_stats/a.out",
"symbolFilePath": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_dsym_binary_has_symfile_in_stats/a.out.dSYM/Contents/Resources/DWARF/a.out",
"symbolTableIndexTime": 7.9999999999999996e-06,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 7.8999999999999996e-05,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx12.0.0",
"uuid": "E1F7D85B-3A42-321E-BF0D-29B103F5F2E3"
},
```
And for the DWARF in .o file case we can see the "symbolFileModuleIdentifiers" in the executable's module stats:
```
"modules": [
{
"debugInfoByteSize": 0,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 0,
"identifier": 4603526968,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_no_dsym_binary_has_symfile_identifiers_in_stats/a.out",
"symbolFileModuleIdentifiers": [
4604429832
],
"symbolTableIndexTime": 7.9999999999999996e-06,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 0.000112,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx12.0.0",
"uuid": "57008BF5-A726-3DE9-B1BF-3A9AD3EE8569"
},
```
And the .o file for 4604429832 looks like:
```
{
"debugInfoByteSize": 1028,
"debugInfoIndexLoadedFromCache": false,
"debugInfoIndexSavedToCache": false,
"debugInfoIndexTime": 0,
"debugInfoParseTime": 6.0999999999999999e-05,
"identifier": 4604429832,
"path": "/Users/gclayton/Documents/src/lldb/main/Debug/lldb-test-build.noindex/commands/statistics/basic/TestStats.test_no_dsym_binary_has_symfile_identifiers_in_stats/main.o",
"symbolTableIndexTime": 0,
"symbolTableLoadedFromCache": false,
"symbolTableParseTime": 0,
"symbolTableSavedToCache": false,
"triple": "arm64-apple-macosx"
}
```
Differential Revision: https://reviews.llvm.org/D119400
2022-02-09 18:48:17 -08:00
|
|
|
if (!symfile_path.empty())
|
|
|
|
|
module.try_emplace("symbolFilePath", symfile_path);
|
|
|
|
|
|
|
|
|
|
if (!symfile_modules.empty()) {
|
|
|
|
|
json::Array symfile_ids;
|
|
|
|
|
for (const auto symfile_id: symfile_modules)
|
|
|
|
|
symfile_ids.emplace_back(symfile_id);
|
|
|
|
|
module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
|
|
|
|
|
}
|
2022-10-31 14:50:04 -07:00
|
|
|
|
|
|
|
|
if (!type_system_stats.empty()) {
|
|
|
|
|
json::Array type_systems;
|
|
|
|
|
for (const auto &entry : type_system_stats) {
|
|
|
|
|
json::Object obj;
|
|
|
|
|
obj.try_emplace(entry.first().str(), entry.second);
|
|
|
|
|
type_systems.emplace_back(std::move(obj));
|
|
|
|
|
}
|
|
|
|
|
module.try_emplace("typeSystemInfo", std::move(type_systems));
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
return module;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-24 15:12:18 -08:00
|
|
|
llvm::json::Value ConstStringStats::ToJSON() const {
|
|
|
|
|
json::Object obj;
|
|
|
|
|
obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
|
|
|
|
|
obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
|
|
|
|
|
obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
json::Value
|
|
|
|
|
TargetStats::ToJSON(Target &target,
|
|
|
|
|
const lldb_private::StatisticsOptions &options) {
|
|
|
|
|
json::Object target_metrics_json;
|
|
|
|
|
ProcessSP process_sp = target.GetProcessSP();
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
const bool summary_only = options.GetSummaryOnly();
|
|
|
|
|
const bool include_modules = options.GetIncludeModules();
|
2024-02-06 19:47:34 -05:00
|
|
|
if (!summary_only) {
|
|
|
|
|
CollectStats(target);
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
json::Array json_module_uuid_array;
|
|
|
|
|
for (auto module_identifier : m_module_identifiers)
|
|
|
|
|
json_module_uuid_array.emplace_back(module_identifier);
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
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());
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
if (include_modules)
|
|
|
|
|
target_metrics_json.try_emplace("moduleIdentifiers",
|
|
|
|
|
std::move(json_module_uuid_array));
|
2021-10-21 16:01:00 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
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());
|
|
|
|
|
}
|
2021-10-20 14:49:09 -07:00
|
|
|
}
|
2024-02-06 19:47:34 -05:00
|
|
|
|
|
|
|
|
// 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);
|
2021-10-26 17:48:42 -07:00
|
|
|
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();
|
2024-02-06 19:47:34 -05:00
|
|
|
if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
|
|
|
|
|
shared_library_event_breakpoint_hit_count += bp->GetHitCount();
|
2021-10-26 17:48:42 -07:00
|
|
|
}
|
2024-02-06 19:47:34 -05:00
|
|
|
|
|
|
|
|
target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
|
|
|
|
|
shared_library_event_breakpoint_hit_count);
|
2021-10-26 17:48:42 -07:00
|
|
|
}
|
|
|
|
|
|
2021-10-27 18:33:17 -07:00
|
|
|
if (process_sp) {
|
2021-11-12 15:26:27 -08:00
|
|
|
uint32_t stop_id = process_sp->GetStopID();
|
|
|
|
|
target_metrics_json.try_emplace("stopCount", stop_id);
|
2021-10-26 17:48:42 -07:00
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
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);
|
2024-08-15 11:26:24 -07:00
|
|
|
target_metrics_json.try_emplace("sourceRealpathAttemptCount",
|
|
|
|
|
m_source_realpath_attempt_count);
|
|
|
|
|
target_metrics_json.try_emplace("sourceRealpathCompatibleCount",
|
|
|
|
|
m_source_realpath_compatible_count);
|
2024-09-10 09:58:43 -07:00
|
|
|
target_metrics_json.try_emplace("summaryProviderStatistics",
|
|
|
|
|
target.GetSummaryStatisticsCache().ToJSON());
|
2021-10-20 14:49:09 -07:00
|
|
|
return target_metrics_json;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetLaunchOrAttachTime() {
|
|
|
|
|
m_launch_or_attach_time = StatsClock::now();
|
2022-12-04 16:51:25 -08:00
|
|
|
m_first_private_stop_time = std::nullopt;
|
2021-10-20 14:49:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetFirstPrivateStopTime() {
|
|
|
|
|
// Launching and attaching has many paths depending on if synchronous mode
|
|
|
|
|
// was used or if we are stopping at the entry point or not. Only set the
|
|
|
|
|
// first stop time if it hasn't already been set.
|
|
|
|
|
if (!m_first_private_stop_time)
|
|
|
|
|
m_first_private_stop_time = StatsClock::now();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::SetFirstPublicStopTime() {
|
|
|
|
|
// Launching and attaching has many paths depending on if synchronous mode
|
|
|
|
|
// was used or if we are stopping at the entry point or not. Only set the
|
|
|
|
|
// first stop time if it hasn't already been set.
|
|
|
|
|
if (!m_first_public_stop_time)
|
|
|
|
|
m_first_public_stop_time = StatsClock::now();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-22 14:32:35 -07:00
|
|
|
void TargetStats::IncreaseSourceMapDeduceCount() {
|
|
|
|
|
++m_source_map_deduce_count;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-15 11:26:24 -07:00
|
|
|
void TargetStats::IncreaseSourceRealpathAttemptCount(uint32_t count) {
|
|
|
|
|
m_source_realpath_attempt_count += count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TargetStats::IncreaseSourceRealpathCompatibleCount(uint32_t count) {
|
|
|
|
|
m_source_realpath_compatible_count += count;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
bool DebuggerStats::g_collecting_stats = false;
|
|
|
|
|
|
2024-02-06 19:47:34 -05:00
|
|
|
llvm::json::Value DebuggerStats::ReportStatistics(
|
|
|
|
|
Debugger &debugger, Target *target,
|
|
|
|
|
const lldb_private::StatisticsOptions &options) {
|
|
|
|
|
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
const bool summary_only = options.GetSummaryOnly();
|
|
|
|
|
const bool load_all_debug_info = options.GetLoadAllDebugInfo();
|
|
|
|
|
const bool include_targets = options.GetIncludeTargets();
|
|
|
|
|
const bool include_modules = options.GetIncludeModules();
|
|
|
|
|
const bool include_transcript = options.GetIncludeTranscript();
|
2024-02-06 19:47:34 -05:00
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
json::Array json_targets;
|
|
|
|
|
json::Array json_modules;
|
|
|
|
|
double symtab_parse_time = 0.0;
|
|
|
|
|
double symtab_index_time = 0.0;
|
2021-10-25 18:03:06 -07:00
|
|
|
double debug_parse_time = 0.0;
|
|
|
|
|
double debug_index_time = 0.0;
|
2021-12-28 10:49:59 -08:00
|
|
|
uint32_t symtabs_loaded = 0;
|
|
|
|
|
uint32_t symtabs_saved = 0;
|
|
|
|
|
uint32_t debug_index_loaded = 0;
|
|
|
|
|
uint32_t debug_index_saved = 0;
|
2021-10-25 18:03:06 -07:00
|
|
|
uint64_t debug_info_size = 0;
|
2024-02-06 19:47:34 -05:00
|
|
|
|
2021-10-21 16:01:00 -07:00
|
|
|
std::vector<ModuleStats> modules;
|
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(
|
|
|
|
|
Module::GetAllocationModuleCollectionMutex());
|
2022-04-20 07:30:53 -07:00
|
|
|
const uint64_t num_modules = Module::GetNumberAllocatedModules();
|
|
|
|
|
uint32_t num_debug_info_enabled_modules = 0;
|
|
|
|
|
uint32_t num_modules_has_debug_info = 0;
|
2022-11-20 09:40:23 -08:00
|
|
|
uint32_t num_modules_with_variable_errors = 0;
|
2022-11-23 20:28:03 -08:00
|
|
|
uint32_t num_modules_with_incomplete_types = 0;
|
2022-04-20 07:30:53 -07:00
|
|
|
uint32_t num_stripped_modules = 0;
|
2021-10-21 16:01:00 -07:00
|
|
|
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
|
|
|
|
|
Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
|
|
|
|
|
ModuleStats module_stat;
|
2022-01-17 15:04:30 +01:00
|
|
|
module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
|
|
|
|
|
module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
|
2021-12-28 10:49:59 -08:00
|
|
|
Symtab *symtab = module->GetSymtab();
|
|
|
|
|
if (symtab) {
|
|
|
|
|
module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
|
|
|
|
|
if (module_stat.symtab_loaded_from_cache)
|
|
|
|
|
++symtabs_loaded;
|
|
|
|
|
module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
|
|
|
|
|
if (module_stat.symtab_saved_to_cache)
|
|
|
|
|
++symtabs_saved;
|
|
|
|
|
}
|
2021-10-25 18:03:06 -07:00
|
|
|
SymbolFile *sym_file = module->GetSymbolFile();
|
|
|
|
|
if (sym_file) {
|
2024-02-06 19:47:34 -05:00
|
|
|
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());
|
|
|
|
|
}
|
2021-12-28 10:49:59 -08:00
|
|
|
module_stat.debug_info_index_loaded_from_cache =
|
|
|
|
|
sym_file->GetDebugInfoIndexWasLoadedFromCache();
|
|
|
|
|
if (module_stat.debug_info_index_loaded_from_cache)
|
|
|
|
|
++debug_index_loaded;
|
|
|
|
|
module_stat.debug_info_index_saved_to_cache =
|
|
|
|
|
sym_file->GetDebugInfoIndexWasSavedToCache();
|
|
|
|
|
if (module_stat.debug_info_index_saved_to_cache)
|
|
|
|
|
++debug_index_saved;
|
2024-02-06 19:47:34 -05:00
|
|
|
module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
|
|
|
|
|
module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
|
2024-02-19 00:33:23 -05:00
|
|
|
module_stat.debug_info_size =
|
|
|
|
|
sym_file->GetDebugInfoSize(load_all_debug_info);
|
2022-04-20 07:30:53 -07:00
|
|
|
module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
|
|
|
|
|
if (module_stat.symtab_stripped)
|
|
|
|
|
++num_stripped_modules;
|
|
|
|
|
module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
|
|
|
|
|
module_stat.debug_info_size > 0;
|
2022-09-22 17:54:06 -07:00
|
|
|
module_stat.debug_info_had_variable_errors =
|
|
|
|
|
sym_file->GetDebugInfoHadFrameVariableErrors();
|
2022-04-20 07:30:53 -07:00
|
|
|
if (module_stat.debug_info_enabled)
|
|
|
|
|
++num_debug_info_enabled_modules;
|
|
|
|
|
if (module_stat.debug_info_size > 0)
|
|
|
|
|
++num_modules_has_debug_info;
|
2022-11-20 09:40:23 -08:00
|
|
|
if (module_stat.debug_info_had_variable_errors)
|
|
|
|
|
++num_modules_with_variable_errors;
|
2021-10-25 18:03:06 -07:00
|
|
|
}
|
2021-10-21 16:01:00 -07:00
|
|
|
symtab_parse_time += module_stat.symtab_parse_time;
|
|
|
|
|
symtab_index_time += module_stat.symtab_index_time;
|
2021-10-25 18:03:06 -07:00
|
|
|
debug_parse_time += module_stat.debug_parse_time;
|
|
|
|
|
debug_index_time += module_stat.debug_index_time;
|
|
|
|
|
debug_info_size += module_stat.debug_info_size;
|
2022-11-14 16:24:36 -08:00
|
|
|
module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
|
2022-10-31 14:50:04 -07:00
|
|
|
if (auto stats = ts->ReportStatistics())
|
|
|
|
|
module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
|
2022-11-23 20:28:03 -08:00
|
|
|
if (ts->GetHasForcefullyCompletedTypes())
|
|
|
|
|
module_stat.debug_info_had_incomplete_types = true;
|
2022-10-31 14:50:04 -07:00
|
|
|
return true;
|
|
|
|
|
});
|
2022-11-23 20:28:03 -08:00
|
|
|
if (module_stat.debug_info_had_incomplete_types)
|
|
|
|
|
++num_modules_with_incomplete_types;
|
|
|
|
|
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
if (include_modules) {
|
2024-02-06 19:47:34 -05:00
|
|
|
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());
|
|
|
|
|
}
|
2021-10-21 16:01:00 -07:00
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
json::Object global_stats{
|
2021-10-21 16:01:00 -07:00
|
|
|
{"totalSymbolTableParseTime", symtab_parse_time},
|
|
|
|
|
{"totalSymbolTableIndexTime", symtab_index_time},
|
2021-12-28 10:49:59 -08:00
|
|
|
{"totalSymbolTablesLoadedFromCache", symtabs_loaded},
|
|
|
|
|
{"totalSymbolTablesSavedToCache", symtabs_saved},
|
2021-10-25 18:03:06 -07:00
|
|
|
{"totalDebugInfoParseTime", debug_parse_time},
|
|
|
|
|
{"totalDebugInfoIndexTime", debug_index_time},
|
2021-12-28 10:49:59 -08:00
|
|
|
{"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
|
|
|
|
|
{"totalDebugInfoIndexSavedToCache", debug_index_saved},
|
2021-10-25 18:03:06 -07:00
|
|
|
{"totalDebugInfoByteSize", debug_info_size},
|
2022-04-20 07:30:53 -07:00
|
|
|
{"totalModuleCount", num_modules},
|
|
|
|
|
{"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
|
2022-11-20 09:40:23 -08:00
|
|
|
{"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
|
2024-02-05 13:17:29 -08:00
|
|
|
{"totalModuleCountWithIncompleteTypes",
|
|
|
|
|
num_modules_with_incomplete_types},
|
2022-04-20 07:30:53 -07:00
|
|
|
{"totalDebugInfoEnabled", num_debug_info_enabled_modules},
|
|
|
|
|
{"totalSymbolTableStripped", num_stripped_modules},
|
2021-10-20 14:49:09 -07:00
|
|
|
};
|
2024-02-06 19:47:34 -05:00
|
|
|
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
if (include_targets) {
|
|
|
|
|
if (target) {
|
2024-02-06 19:47:34 -05:00
|
|
|
json_targets.emplace_back(target->ReportStatistics(options));
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
} else {
|
|
|
|
|
for (const auto &target : debugger.GetTargetList().Targets())
|
|
|
|
|
json_targets.emplace_back(target->ReportStatistics(options));
|
|
|
|
|
}
|
|
|
|
|
global_stats.try_emplace("targets", std::move(json_targets));
|
2024-02-06 19:47:34 -05:00
|
|
|
}
|
|
|
|
|
|
2024-06-06 13:18:06 -07:00
|
|
|
ConstStringStats const_string_stats;
|
|
|
|
|
json::Object json_memory{
|
|
|
|
|
{"strings", const_string_stats.ToJSON()},
|
|
|
|
|
};
|
|
|
|
|
global_stats.try_emplace("memory", std::move(json_memory));
|
2024-02-06 19:47:34 -05:00
|
|
|
if (!summary_only) {
|
|
|
|
|
json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
|
|
|
|
|
global_stats.try_emplace("commands", std::move(cmd_stats));
|
|
|
|
|
}
|
|
|
|
|
|
[lldb] Add/change options in `statistics dump` to control what sections are dumped (#95075)
# Added/changed options
The following options are **added** to the `statistics dump` command:
* `--targets=bool`: Boolean. Dumps the `targets` section.
* `--modules=bool`: Boolean. Dumps the `modules` section.
When both options are given, the field `moduleIdentifiers` will be
dumped for each target in the `targets` section.
The following options are **changed**:
* `--transcript=bool`: Changed to a boolean. Dumps the `transcript`
section.
# Behavior of `statistics dump` with various options
The behavior is **backward compatible**:
- When no options are provided, `statistics dump` dumps all sections.
- When `--summary` is provided, only dumps the summary info.
**New** behavior:
- `--targets=bool`, `--modules=bool`, `--transcript=bool` overrides the
above "default".
For **example**:
- `statistics dump --modules=false` dumps summary + targets +
transcript. No modules.
- `statistics dump --summary --targets=true --transcript=true` dumps
summary + targets (in summary mode) + transcript.
# Added options into public API
In `SBStatisticsOptions`, add:
* `Set/GetIncludeTargets`
* `Set/GetIncludeModules`
* `Set/GetIncludeTranscript`
**Alternative considered**: Thought about adding
`Set/GetIncludeSections(string sections_spec)`, which receives a
comma-separated list of section names to be included ("targets",
"modules", "transcript"). The **benefit** of this approach is that the
API is more future-proof when it comes to possible adding/changing of
section names. **However**, I feel the section names are likely to
remain unchanged for a while - it's not like we plan to make big changes
to the output of `statistics dump` any time soon. The **downsides** of
this approach are: 1\ the readability of the API is worse (requires
reading doc to understand what string can be accepted), 2\ string input
are more prone to human error (e.g. typo "target" instead of expected
"targets").
# Tests
```
bin/llvm-lit -sv ../external/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py
```
```
./tools/lldb/unittests/Interpreter/InterpreterTests
```
New test cases have been added to verify:
* Different sections are dumped/not dumped when different
`StatisticsOptions` are given through command line (CLI or
`HandleCommand`; see `test_sections_existence_through_command`) or API
(see `test_sections_existence_through_api`).
* The order in which the options are given in command line does not
matter (see `test_order_of_options_do_not_matter`).
---------
Co-authored-by: Roy Shi <royshi@meta.com>
2024-06-18 17:21:20 -07:00
|
|
|
if (include_modules) {
|
|
|
|
|
global_stats.try_emplace("modules", std::move(json_modules));
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-03 13:52:03 -07:00
|
|
|
if (include_transcript) {
|
|
|
|
|
// When transcript is available, add it to the to-be-returned statistics.
|
|
|
|
|
//
|
|
|
|
|
// NOTE:
|
|
|
|
|
// When the statistics is polled by an LLDB command:
|
|
|
|
|
// - The transcript in the returned statistics *will NOT* contain the
|
|
|
|
|
// returned statistics itself (otherwise infinite recursion).
|
|
|
|
|
// - The returned statistics *will* be written to the internal transcript
|
|
|
|
|
// buffer. It *will* appear in the next statistcs or transcript poll.
|
|
|
|
|
//
|
|
|
|
|
// For example, let's say the following commands are run in order:
|
|
|
|
|
// - "version"
|
|
|
|
|
// - "statistics dump" <- call it "A"
|
|
|
|
|
// - "statistics dump" <- call it "B"
|
|
|
|
|
// The output of "A" will contain the transcript of "version" and
|
|
|
|
|
// "statistics dump" (A), with the latter having empty output. The output
|
|
|
|
|
// of B will contain the trascnript of "version", "statistics dump" (A),
|
|
|
|
|
// "statistics dump" (B), with A's output populated and B's output empty.
|
|
|
|
|
const StructuredData::Array &transcript =
|
|
|
|
|
debugger.GetCommandInterpreter().GetTranscript();
|
|
|
|
|
if (transcript.GetSize() != 0) {
|
|
|
|
|
std::string buffer;
|
|
|
|
|
llvm::raw_string_ostream ss(buffer);
|
|
|
|
|
json::OStream json_os(ss);
|
|
|
|
|
transcript.Serialize(json_os);
|
2024-09-16 00:26:51 -04:00
|
|
|
if (auto json_transcript = llvm::json::parse(buffer))
|
2024-06-03 13:52:03 -07:00
|
|
|
global_stats.try_emplace("transcript",
|
|
|
|
|
std::move(json_transcript.get()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-20 14:49:09 -07:00
|
|
|
return std::move(global_stats);
|
|
|
|
|
}
|
2024-09-10 09:58:43 -07:00
|
|
|
|
|
|
|
|
llvm::json::Value SummaryStatistics::ToJSON() const {
|
|
|
|
|
return json::Object{{
|
|
|
|
|
{"name", GetName()},
|
|
|
|
|
{"type", GetSummaryKindName()},
|
|
|
|
|
{"count", GetSummaryCount()},
|
|
|
|
|
{"totalTime", GetTotalTime()},
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
json::Value SummaryStatisticsCache::ToJSON() {
|
|
|
|
|
std::lock_guard<std::mutex> guard(m_map_mutex);
|
|
|
|
|
json::Array json_summary_stats;
|
|
|
|
|
for (const auto &summary_stat : m_summary_stats_map)
|
|
|
|
|
json_summary_stats.emplace_back(summary_stat.second->ToJSON());
|
|
|
|
|
|
|
|
|
|
return json_summary_stats;
|
|
|
|
|
}
|