Skip to content

Commit 654b520

Browse files
[lldb][swift] Cache and lazily-evaluate Task names in OperatingSystemSwiftTasks
Computing a Task name can be an expensive operation, especially over slower connections to the inferior process. To improve this situation, this patch: * Makes the computation lazy, and * Caches the result of the computation (a task name is immutable). The first point is the most important, as prior to this we were computing the task name on every stop, even when the same MemoryThread was reused between two consecutive stops. On local testing with a wired connection, this reduces stepping time by around 20-30ms, out of an average of 230ms.
1 parent dc10b40 commit 654b520

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.cpp

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,49 @@ void OperatingSystemSwiftTasks::Terminate() {
3838
PluginManager::UnregisterPlugin(CreateInstance);
3939
}
4040

41+
/// A wrapper around ThreadMemory providing lazy name evaluation, as this is
42+
/// expensive to compute for Swift Task.
43+
class SwiftTaskThreadMemory : public ThreadMemory {
44+
public:
45+
SwiftTaskThreadMemory(lldb_private::Process &process, lldb::tid_t tid,
46+
lldb::addr_t register_data_addr)
47+
: ThreadMemory(process, tid, register_data_addr) {}
48+
49+
void SetTaskAddr(lldb::addr_t task_addr) { m_task_addr = task_addr; }
50+
51+
const char *GetName() override {
52+
if (m_task_name.empty())
53+
m_task_name = FindTaskName();
54+
return m_task_name.c_str();
55+
}
56+
57+
private:
58+
std::string GetDefaultTaskName() const {
59+
return llvm::formatv("Task {0}", GetID());
60+
}
61+
62+
/// If possible, read a user-provided task name from memory, otherwise use a
63+
/// default name. This never returns an empty string.
64+
std::string FindTaskName() const {
65+
llvm::Expected<std::optional<std::string>> task_name =
66+
GetTaskName(m_task_addr, *GetProcess());
67+
if (auto err = task_name.takeError()) {
68+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
69+
"OperatingSystemSwiftTasks: failed while looking for name "
70+
"of task {1:x}: {0}",
71+
m_task_addr);
72+
return GetDefaultTaskName();
73+
}
74+
75+
if (!task_name->has_value())
76+
return GetDefaultTaskName();
77+
return llvm::formatv("{0} (Task {1})", *task_name, GetID());
78+
}
79+
80+
std::string m_task_name = "";
81+
lldb::addr_t m_task_addr = LLDB_INVALID_ADDRESS;
82+
};
83+
4184
OperatingSystem *OperatingSystemSwiftTasks::CreateInstance(Process *process,
4285
bool force) {
4386
if (!process || !process->GetTarget().GetSwiftUseTasksPlugin())
@@ -78,9 +121,9 @@ OperatingSystemSwiftTasks::OperatingSystemSwiftTasks(
78121
lldb_private::Process &process)
79122
: OperatingSystem(&process) {}
80123

81-
ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
82-
ThreadList &old_thread_list, uint64_t task_id,
83-
std::optional<std::string> task_name) {
124+
ThreadSP
125+
OperatingSystemSwiftTasks::FindOrCreateSwiftThread(ThreadList &old_thread_list,
126+
uint64_t task_id) {
84127
// Mask higher bits to avoid conflicts with core thread IDs.
85128
uint64_t masked_task_id = 0x0000000f00000000 | task_id;
86129

@@ -89,15 +132,8 @@ ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
89132
IsOperatingSystemPluginThread(old_thread))
90133
return old_thread;
91134

92-
std::string name;
93-
if (task_name)
94-
name = llvm::formatv("{0} (Task {1})", *task_name, task_id);
95-
else
96-
name = llvm::formatv("Task {0}", task_id);
97-
98-
return std::make_shared<ThreadMemoryProvidingName>(*m_process, masked_task_id,
99-
/*register_data_addr*/ 0,
100-
name);
135+
return std::make_shared<SwiftTaskThreadMemory>(*m_process, masked_task_id,
136+
/*register_data_addr*/ 0);
101137
}
102138

103139
static std::optional<addr_t> FindTaskAddress(TaskInspector &task_inspector,
@@ -132,19 +168,6 @@ static std::optional<uint64_t> FindTaskId(addr_t task_addr, Process &process) {
132168
return task_id;
133169
}
134170

135-
static std::optional<std::string> FindTaskName(addr_t task_addr,
136-
Process &process) {
137-
auto task_name_or_err = GetTaskName(task_addr, process);
138-
if (auto err = task_name_or_err.takeError()) {
139-
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
140-
"OperatingSystemSwiftTasks: failed while looking for name "
141-
"of task {1:x}: {0}",
142-
task_addr);
143-
return {};
144-
}
145-
return *task_name_or_err;
146-
}
147-
148171
bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
149172
ThreadList &core_thread_list,
150173
ThreadList &new_thread_list) {
@@ -173,9 +196,9 @@ bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
173196
continue;
174197
}
175198

176-
ThreadSP swift_thread = FindOrCreateSwiftThread(
177-
old_thread_list, *task_id, FindTaskName(*task_addr, *m_process));
199+
ThreadSP swift_thread = FindOrCreateSwiftThread(old_thread_list, *task_id);
178200
swift_thread->SetBackingThread(real_thread);
201+
static_cast<SwiftTaskThreadMemory &>(*swift_thread).SetTaskAddr(*task_addr);
179202
new_thread_list.AddThread(swift_thread);
180203
LLDB_LOGF(log,
181204
"OperatingSystemSwiftTasks: mapping thread IDs: %" PRIx64

lldb/source/Plugins/OperatingSystem/SwiftTasks/OperatingSystemSwiftTasks.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ class OperatingSystemSwiftTasks : public OperatingSystem {
5050
/// If a thread for task_id had been created in the last stop, return it.
5151
/// Otherwise, create a new MemoryThread for it.
5252
lldb::ThreadSP FindOrCreateSwiftThread(ThreadList &old_thread_list,
53-
uint64_t task_id,
54-
std::optional<std::string> task_name);
53+
uint64_t task_id);
5554

5655
/// A cache for task addr locations, which are expensive to compute but
5756
/// immutable.

0 commit comments

Comments
 (0)