Skip to content

Commit 4d4f808

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 45d8e62 commit 4d4f808

File tree

2 files changed

+57
-30
lines changed

2 files changed

+57
-30
lines changed

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

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,54 @@ 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+
/// Updates the backing thread of this Task, as well as the location where the
50+
/// task pointer is stored.
51+
void UpdateBackingThread(Thread &new_backing_thread, lldb::addr_t task_addr) {
52+
SetBackingThread(new_backing_thread);
53+
m_task_addr = task_addr;
54+
}
55+
56+
const char *GetName() override {
57+
if (m_task_name.empty())
58+
m_task_name = FindTaskName();
59+
return m_task_name.c_str();
60+
}
61+
62+
private:
63+
std::string GetDefaultTaskName() const {
64+
return llvm::formatv("Task {0}", GetID());
65+
}
66+
67+
/// If possible, read a user-provided task name from memory, otherwise use a
68+
/// default name. This never returns an empty string.
69+
std::string FindTaskName() const {
70+
llvm::Expected<std::optional<std::string>> task_name =
71+
GetTaskName(m_task_addr, *GetProcess());
72+
if (auto err = task_name.takeError()) {
73+
LLDB_LOG_ERROR(GetLog(LLDBLog::OS), std::move(err),
74+
"OperatingSystemSwiftTasks: failed while looking for name "
75+
"of task {1:x}: {0}",
76+
m_task_addr);
77+
return GetDefaultTaskName();
78+
}
79+
80+
if (!task_name->has_value())
81+
return GetDefaultTaskName();
82+
return llvm::formatv("{0} (Task {1})", *task_name, GetID());
83+
}
84+
85+
std::string m_task_name = "";
86+
lldb::addr_t m_task_addr = LLDB_INVALID_ADDRESS;
87+
};
88+
4189
OperatingSystem *OperatingSystemSwiftTasks::CreateInstance(Process *process,
4290
bool force) {
4391
if (!process || !process->GetTarget().GetSwiftUseTasksPlugin())
@@ -78,9 +126,9 @@ OperatingSystemSwiftTasks::OperatingSystemSwiftTasks(
78126
lldb_private::Process &process)
79127
: OperatingSystem(&process) {}
80128

81-
ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
82-
ThreadList &old_thread_list, uint64_t task_id,
83-
std::optional<std::string> task_name) {
129+
ThreadSP
130+
OperatingSystemSwiftTasks::FindOrCreateSwiftThread(ThreadList &old_thread_list,
131+
uint64_t task_id) {
84132
// Mask higher bits to avoid conflicts with core thread IDs.
85133
uint64_t masked_task_id = 0x0000000f00000000 | task_id;
86134

@@ -89,15 +137,8 @@ ThreadSP OperatingSystemSwiftTasks::FindOrCreateSwiftThread(
89137
IsOperatingSystemPluginThread(old_thread))
90138
return old_thread;
91139

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);
140+
return std::make_shared<SwiftTaskThreadMemory>(*m_process, masked_task_id,
141+
/*register_data_addr*/ 0);
101142
}
102143

103144
static std::optional<addr_t> FindTaskAddress(TaskInspector &task_inspector,
@@ -132,19 +173,6 @@ static std::optional<uint64_t> FindTaskId(addr_t task_addr, Process &process) {
132173
return task_id;
133174
}
134175

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-
148176
bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
149177
ThreadList &core_thread_list,
150178
ThreadList &new_thread_list) {
@@ -173,9 +201,9 @@ bool OperatingSystemSwiftTasks::UpdateThreadList(ThreadList &old_thread_list,
173201
continue;
174202
}
175203

176-
ThreadSP swift_thread = FindOrCreateSwiftThread(
177-
old_thread_list, *task_id, FindTaskName(*task_addr, *m_process));
178-
swift_thread->SetBackingThread(real_thread);
204+
ThreadSP swift_thread = FindOrCreateSwiftThread(old_thread_list, *task_id);
205+
static_cast<SwiftTaskThreadMemory &>(*swift_thread)
206+
.UpdateBackingThread(real_thread, *task_addr);
179207
new_thread_list.AddThread(swift_thread);
180208
LLDB_LOGF(log,
181209
"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)