Skip to content

Commit 0b88256

Browse files
zarvoxkentonv
authored andcommitted
Use a hash map for thread id lookup, rather than a linked list
When using node-fibers, we find ourselves spending 65% of our CPU time traversing the thread table linked list. Let's try a real data structure.
1 parent 0792b61 commit 0b88256

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

deps/v8/src/isolate.cc

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <fstream> // NOLINT(readability/streams)
1010
#include <sstream>
11+
#include <unordered_map>
1112

1213
#include "src/assembler-inl.h"
1314
#include "src/ast/ast-value-factory.h"
@@ -2095,7 +2096,7 @@ char* Isolate::RestoreThread(char* from) {
20952096

20962097

20972098
Isolate::ThreadDataTable::ThreadDataTable()
2098-
: list_(NULL) {
2099+
: table_() {
20992100
}
21002101

21012102

@@ -2155,34 +2156,38 @@ Isolate::PerIsolateThreadData::~PerIsolateThreadData() {
21552156
Isolate::PerIsolateThreadData*
21562157
Isolate::ThreadDataTable::Lookup(Isolate* isolate,
21572158
ThreadId thread_id) {
2158-
for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
2159-
if (data->Matches(isolate, thread_id)) return data;
2160-
}
2159+
// We assume thread_ids are unique per-process, not just per-isolate.
2160+
// I hope this winds up being true.
2161+
auto t = table_.find(thread_id);
2162+
if (t == table_.end()) return NULL;
2163+
auto data = t->second;
2164+
if (data->Matches(isolate, thread_id)) return data;
21612165
return NULL;
21622166
}
21632167

21642168

21652169
void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
2166-
if (list_ != NULL) list_->prev_ = data;
2167-
data->next_ = list_;
2168-
list_ = data;
2170+
table_[data->thread_id_] = data;
21692171
}
21702172

21712173

21722174
void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
2173-
if (list_ == data) list_ = data->next_;
2174-
if (data->next_ != NULL) data->next_->prev_ = data->prev_;
2175-
if (data->prev_ != NULL) data->prev_->next_ = data->next_;
2175+
table_.erase(data->thread_id_);
21762176
delete data;
21772177
}
21782178

21792179

21802180
void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
2181-
PerIsolateThreadData* data = list_;
2182-
while (data != NULL) {
2183-
PerIsolateThreadData* next = data->next_;
2184-
if (data->isolate() == isolate) Remove(data);
2185-
data = next;
2181+
std::vector<PerIsolateThreadData*> values_to_remove;
2182+
for (auto& x: table_) {
2183+
PerIsolateThreadData* value = x.second;
2184+
if (value->isolate_ == isolate) {
2185+
values_to_remove.push_back(value);
2186+
}
2187+
}
2188+
2189+
for (auto& value: values_to_remove) {
2190+
Remove(value);
21862191
}
21872192
}
21882193

deps/v8/src/isolate.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cstddef>
99
#include <memory>
1010
#include <queue>
11+
#include <unordered_map>
1112

1213
#include "include/v8-debug.h"
1314
#include "src/allocation.h"
@@ -243,6 +244,10 @@ class ThreadId {
243244
return *this;
244245
}
245246

247+
bool operator==(const ThreadId& other) const {
248+
return Equals(other);
249+
}
250+
246251
// Returns ThreadId for current thread.
247252
static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
248253

@@ -283,6 +288,13 @@ class ThreadId {
283288
friend class Isolate;
284289
};
285290

291+
template <class T> struct ThreadIdHasher;
292+
template<> struct ThreadIdHasher<ThreadId> {
293+
std::size_t operator()(ThreadId const& t) const {
294+
// passthrough to std::hash on the thread id int
295+
return std::hash<int>()(t.ToInteger());
296+
}
297+
};
286298

287299
#define FIELD_ACCESSOR(type, name) \
288300
inline void set_##name(type v) { name##_ = v; } \
@@ -1347,7 +1359,7 @@ class Isolate {
13471359
void RemoveAllThreads(Isolate* isolate);
13481360

13491361
private:
1350-
PerIsolateThreadData* list_;
1362+
std::unordered_map<ThreadId, PerIsolateThreadData*, ThreadIdHasher<ThreadId> > table_;
13511363
};
13521364

13531365
// These items form a stack synchronously with threads Enter'ing and Exit'ing

0 commit comments

Comments
 (0)