Skip to content

Commit 377e888

Browse files
committed
[LLDB] Add progress updates for reflection metadata loading
When debugging locally, parsing reflection metadata is instant. But when debugging over a slow network connection the amount of memory read packets being sent back and forth can indtroduce significan delays. To meake is easier to diagnose why an operation is stalling and to provide users with feedback about what LDB is doing this patch introduces a progress update in GetSwiftRuntimTypeInfo(). LLDB only publishes at meast 1 progress event every 20ms, so this is (visually) and performance-wise a noop wehen debugging locally.
1 parent 47e68f0 commit 377e888

File tree

4 files changed

+56
-9
lines changed

4 files changed

+56
-9
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "swift/Demangling/Demangle.h"
2020
#include "llvm/Support/MathExtras.h"
21+
#include "llvm/Support/raw_ostream.h"
2122

2223
using namespace lldb;
2324
using namespace lldb_private;
@@ -416,16 +417,27 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address,
416417
Log *log = GetLog(LLDBLog::Types);
417418

418419
auto format_string = [](const std::string &dest) {
419-
StreamString stream;
420-
for (auto c : dest) {
421-
if (c >= 32 && c <= 127) {
422-
stream << c;
423-
} else {
424-
stream << "\\0";
425-
stream.PutHex8(c);
426-
}
420+
std::string result;
421+
llvm::raw_string_ostream s(result);
422+
llvm::printEscapedString(dest, s);
423+
return result;
424+
};
425+
/// Very quickly (this is a high-firing event), copy a few
426+
/// human-readable bytes usable as detail in the progress update.
427+
auto short_string = [](const std::string &dest) {
428+
std::string result;
429+
result.reserve(24);
430+
size_t end = std::min<size_t>(dest.size(), 24);
431+
for (size_t i = 0; i < end; ++i) {
432+
signed char c = dest[i];
433+
result.append(1, c > 32 ? c : '.');
427434
}
428-
return std::string(stream.GetData());
435+
if (end < dest.size()) {
436+
result[21] = '.';
437+
result[22] = '.';
438+
result[23] = '.';
439+
}
440+
return result;
429441
};
430442
LLDB_LOGV(log, "[MemoryReader] asked to read string data at address {0:x}",
431443
address.getRawAddress());
@@ -463,6 +475,8 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address,
463475
!readMetadataFromFileCacheEnabled() || !addr.IsSectionOffset();
464476
target.ReadCStringFromMemory(addr, dest, error, force_live_memory);
465477
if (error.Success()) {
478+
if (m_progress_callback)
479+
m_progress_callback(short_string(dest));
466480
LLDB_LOGV(log, "[MemoryReader] memory read returned string: \"{0}\"",
467481
format_string(dest));
468482
return true;

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
105105
/// Returns whether the filecache optimization is enabled or not.
106106
bool readMetadataFromFileCacheEnabled() const;
107107

108+
/// Set or clear the progress callback.
109+
void SetProgressCallback(
110+
std::function<void(llvm::StringRef)> progress_callback = {}) {
111+
m_progress_callback = progress_callback;
112+
}
113+
108114
protected:
109115
bool readRemoteAddressImpl(swift::remote::RemoteAddress address,
110116
swift::remote::RemoteAddress &out,
@@ -166,6 +172,8 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
166172
/// The set of modules where we should read memory from the symbol file's
167173
/// object file instead of the main object file.
168174
llvm::SmallSet<lldb::ModuleSP, 8> m_modules_with_metadata_in_symbol_obj_file;
175+
/// A callback to update a progress event.
176+
std::function<void(llvm::StringRef)> m_progress_callback;
169177
};
170178
} // namespace lldb_private
171179
#endif

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,22 @@ std::optional<uint64_t> SwiftLanguageRuntime::GetMemberVariableOffset(
608608

609609
namespace {
610610

611+
class ProgressRAII {
612+
Progress m_progress;
613+
LLDBMemoryReader &m_memory_reader;
614+
public:
615+
ProgressRAII(std::string title, Debugger *debugger,
616+
LLDBMemoryReader &memory_reader)
617+
: m_progress(title, {}, {}, debugger,
618+
Progress::kDefaultHighFrequencyReportTime),
619+
m_memory_reader(memory_reader) {
620+
m_memory_reader.SetProgressCallback([&](StringRef message) {
621+
m_progress.Increment(1, message.str());
622+
});
623+
}
624+
~ProgressRAII() { m_memory_reader.SetProgressCallback(); };
625+
};
626+
611627
CompilerType GetTypeFromTypeRef(TypeSystemSwiftTypeRef &ts,
612628
const swift::reflection::TypeRef *type_ref,
613629
swift::Mangle::ManglingFlavor flavor) {
@@ -3480,6 +3496,14 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo(
34803496
if (!reflection_ctx)
34813497
return llvm::createStringError("no reflection context");
34823498

3499+
// On remove connections downloading reflection metadata can be a bottleneck.
3500+
auto flavor = GetManglingFlavor(type.GetMangledTypeName());
3501+
static std::string g_debuginfo = "Loading debug info";
3502+
static std::string g_reflection = "Loading reflection metadata";
3503+
ProgressRAII progress(
3504+
flavor == swift::Mangle::ManglingFlavor::Embedded ? g_debuginfo
3505+
: g_reflection,
3506+
&GetProcess().GetTarget().GetDebugger(), *GetMemoryReader());
34833507
LLDBTypeInfoProvider provider(*this, ts);
34843508
return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider,
34853509
ts.GetDescriptorFinder());

lldb/test/API/functionalities/progress_reporting/swift_progress_reporting/TestSwiftProgressReporting.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_swift_progress_report(self):
4141
"Importing dependencies for main.swift",
4242
"Importing dependencies for main.swift: Foundation",
4343
"Importing Swift standard library",
44+
"Loading reflection metadata",
4445
]
4546

4647
importing_swift_reports = []

0 commit comments

Comments
 (0)