[lldb][Progress] Separate title and details (#77547)

Per this RFC:
https://discourse.llvm.org/t/rfc-improve-lldb-progress-reporting/75717
on improving progress reports, this commit separates the title field and
details field so that the title specifies the category that the progress
report falls under. The details field is added as a part of the
constructor for progress reports and by default is an empty string. In addition, changes the total amount of progress completed into a std::optional. Also
updates the test to check for details being correctly reported from the
event structured data dictionary.
This commit is contained in:
Chelsea Cassanova 2024-01-16 07:57:18 -08:00 committed by GitHub
parent 77610dd104
commit f1ef910b97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 33 deletions

View File

@ -20,9 +20,10 @@ class Stream;
class ProgressEventData : public EventData {
public:
ProgressEventData(uint64_t progress_id, std::string title, std::string update,
uint64_t completed, uint64_t total, bool debugger_specific)
: m_title(std::move(title)), m_details(std::move(update)),
ProgressEventData(uint64_t progress_id, std::string title,
std::string details, uint64_t completed, uint64_t total,
bool debugger_specific)
: m_title(std::move(title)), m_details(std::move(details)),
m_id(progress_id), m_completed(completed), m_total(total),
m_debugger_specific(debugger_specific) {}

View File

@ -64,12 +64,13 @@ public:
/// @param [in] title The title of this progress activity.
///
/// @param [in] total The total units of work to be done if specified, if
/// set to UINT64_MAX then an indeterminate progress indicator should be
/// set to std::nullopt then an indeterminate progress indicator should be
/// displayed.
///
/// @param [in] debugger An optional debugger pointer to specify that this
/// progress is to be reported only to specific debuggers.
Progress(std::string title, uint64_t total = UINT64_MAX,
Progress(std::string title, std::string details = {},
std::optional<uint64_t> total = std::nullopt,
lldb_private::Debugger *debugger = nullptr);
/// Destroy the progress object.
@ -89,20 +90,23 @@ public:
/// @param [in] amount The amount to increment m_completed by.
///
/// @param [in] an optional message associated with this update.
void Increment(uint64_t amount = 1, std::string update = {});
void Increment(uint64_t amount = 1,
std::optional<std::string> updated_detail = {});
private:
void ReportProgress(std::string update = {});
void ReportProgress();
static std::atomic<uint64_t> g_id;
/// The title of the progress activity.
std::string m_title;
std::string m_details;
std::mutex m_mutex;
/// A unique integer identifier for progress reporting.
const uint64_t m_id;
/// How much work ([0...m_total]) that has been completed.
uint64_t m_completed;
/// Total amount of work, UINT64_MAX for non deterministic progress.
const uint64_t m_total;
/// Total amount of work, use a std::nullopt in the constructor for non
/// deterministic progress.
uint64_t m_total;
/// The optional debugger ID to report progress to. If this has no value then
/// all debuggers will receive this event.
std::optional<lldb::user_id_t> m_debugger_id;

View File

@ -11,15 +11,22 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Utility/StreamString.h"
#include <optional>
using namespace lldb;
using namespace lldb_private;
std::atomic<uint64_t> Progress::g_id(0);
Progress::Progress(std::string title, uint64_t total,
Progress::Progress(std::string title, std::string details,
std::optional<uint64_t> total,
lldb_private::Debugger *debugger)
: m_title(title), m_id(++g_id), m_completed(0), m_total(total) {
assert(total > 0);
: m_title(title), m_details(details), m_id(++g_id), m_completed(0),
m_total(1) {
assert(total == std::nullopt || total > 0);
if (total)
m_total = *total;
if (debugger)
m_debugger_id = debugger->GetID();
std::lock_guard<std::mutex> guard(m_mutex);
@ -35,25 +42,28 @@ Progress::~Progress() {
ReportProgress();
}
void Progress::Increment(uint64_t amount, std::string update) {
void Progress::Increment(uint64_t amount,
std::optional<std::string> updated_detail) {
if (amount > 0) {
std::lock_guard<std::mutex> guard(m_mutex);
if (updated_detail)
m_details = std::move(updated_detail.value());
// Watch out for unsigned overflow and make sure we don't increment too
// much and exceed m_total.
if (amount > (m_total - m_completed))
if (m_total && (amount > (m_total - m_completed)))
m_completed = m_total;
else
m_completed += amount;
ReportProgress(update);
ReportProgress();
}
}
void Progress::ReportProgress(std::string update) {
void Progress::ReportProgress() {
if (!m_complete) {
// Make sure we only send one notification that indicates the progress is
// complete.
// complete
m_complete = m_completed == m_total;
Debugger::ReportProgress(m_id, m_title, std::move(update), m_completed,
m_total, m_debugger_id);
Debugger::ReportProgress(m_id, m_title, m_details, m_completed, m_total,
m_debugger_id);
}
}

View File

@ -2897,9 +2897,8 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
if (!module_sp)
return;
Progress progress(
llvm::formatv("Parsing symbol table for {0}",
m_file.GetFilename().AsCString("<Unknown>")));
Progress progress("Parsing symbol table",
m_file.GetFilename().AsCString("<Unknown>"));
ElapsedTime elapsed(module_sp->GetSymtabParseTime());
// We always want to use the main object file so we (hopefully) only have one

View File

@ -2225,7 +2225,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
const char *file_name = file.GetFilename().AsCString("<Unknown>");
LLDB_SCOPED_TIMERF("ObjectFileMachO::ParseSymtab () module = %s", file_name);
LLDB_LOG(log, "Parsing symbol table for {0}", file_name);
Progress progress(llvm::formatv("Parsing symbol table for {0}", file_name));
Progress progress("Parsing symbol table", file_name);
llvm::MachO::symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0};
llvm::MachO::linkedit_data_command function_starts_load_command = {0, 0, 0, 0};

View File

@ -75,9 +75,8 @@ void ManualDWARFIndex::Index() {
// Include 2 passes per unit to index for extracting DIEs from the unit and
// indexing the unit, and then 8 extra entries for finalizing each index set.
const uint64_t total_progress = units_to_index.size() * 2 + 8;
Progress progress(
llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()),
total_progress);
Progress progress("Manually indexing DWARF", module_desc.GetData(),
total_progress);
std::vector<IndexSet> sets(units_to_index.size());

View File

@ -519,8 +519,6 @@ void SymbolFileDWARF::InitializeObject() {
if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
module_desc.GetData()));
m_index = AppleDWARFIndex::Create(
*GetObjectFile()->GetModule(), apple_names, apple_namespaces,
apple_types, apple_objc, m_context.getOrLoadStrData());
@ -532,8 +530,7 @@ void SymbolFileDWARF::InitializeObject() {
DWARFDataExtractor debug_names;
LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
if (debug_names.GetByteSize() > 0) {
Progress progress(
llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()));
Progress progress("Loading DWARF5 index", module_desc.GetData());
llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
debug_names,

View File

@ -98,9 +98,9 @@ std::optional<FileSpec> SymbolLocatorDefault::LocateExecutableSymbolFile(
FileSystem::Instance().Exists(symbol_file_spec))
return symbol_file_spec;
Progress progress(llvm::formatv(
"Locating external symbol file for {0}",
module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>")));
Progress progress(
"Locating external symbol file",
module_spec.GetFileSpec().GetFilename().AsCString("<Unknown>"));
FileSpecList debug_file_search_paths = default_search_paths;

View File

@ -39,3 +39,5 @@ class TestProgressReporting(TestBase):
progress_data = lldb.SBDebugger.GetProgressDataFromEvent(event)
message = progress_data.GetValueForKey("message").GetStringValue(100)
self.assertGreater(len(message), 0)
details = progress_data.GetValueForKey("details").GetStringValue(100)
self.assertGreater(len(details), 0)