Skip to content

Commit 115a60a

Browse files
committed
thread filter - add a free list
1 parent 1d4efc0 commit 115a60a

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

ddprof-lib/src/main/cpp/flightRecorder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ class Recording {
128128
static char *_java_command;
129129

130130
RecordingBuffer _buf[CONCURRENCY_LEVEL];
131+
// we have several sets to avoid lock contention
132+
// we have a second dimension to allow a switch in the active set
131133
std::unordered_set<int> _thread_ids[CONCURRENCY_LEVEL][2];
132134
std::atomic<int> _active_index{0}; // 0 or 1 globally
133135

ddprof-lib/src/main/cpp/threadFilter.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,24 @@ ThreadFilter::~ThreadFilter() {
1717
std::unique_lock<std::mutex> lock(_slot_mutex);
1818
_slots.clear();
1919
}
20-
2120
ThreadFilter::SlotID ThreadFilter::registerThread() {
21+
int top = _free_list_top.load(std::memory_order_acquire);
22+
for (int i = 0; i < top; ++i) {
23+
int value = _free_list[i].load(std::memory_order_relaxed);
24+
if (value >= 0) {
25+
int expected = value;
26+
if (_free_list[i].compare_exchange_strong(expected, -1, std::memory_order_acq_rel)) {
27+
return value; // Successfully claimed a free slot
28+
}
29+
// If CAS fails, someone else claimed it, continue scanning
30+
}
31+
}
32+
2233
SlotID index = _next_index.fetch_add(1, std::memory_order_relaxed);
2334
if (index >= kMaxThreads) {
2435
return -1;
2536
}
37+
2638
const int outer_idx = index >> kChunkShift;
2739
{
2840
if (outer_idx < static_cast<int>(_slots.size())) {
@@ -46,6 +58,10 @@ void ThreadFilter::clear() {
4658
slot.value.store(-1, std::memory_order_relaxed);
4759
}
4860
}
61+
for (int i = 0; i < kFreeListSize; ++i) {
62+
_free_list[i].store(-1, std::memory_order_relaxed);
63+
}
64+
_free_list_top.store(0, std::memory_order_relaxed);
4965
}
5066

5167
bool ThreadFilter::accept(SlotID slot_id) const {
@@ -73,9 +89,35 @@ void ThreadFilter::remove(SlotID slot_id) {
7389

7490
void ThreadFilter::unregisterThread(SlotID slot_id) {
7591
if (slot_id < 0) return;
92+
7693
int outer_idx = slot_id >> kChunkShift;
7794
int inner_idx = slot_id & kChunkMask;
7895
_slots[outer_idx][inner_idx].value.store(-1, std::memory_order_relaxed);
96+
97+
constexpr int try_limit = 16;
98+
99+
int top = _free_list_top.load(std::memory_order_acquire);
100+
int limit = top < kFreeListSize ? top : kFreeListSize;
101+
int tries = 0;
102+
103+
for (int i = 0; i < limit && tries < try_limit; ++i) {
104+
int value = _free_list[i].load(std::memory_order_relaxed);
105+
if (value == -1) {
106+
int expected = -1;
107+
if (_free_list[i].compare_exchange_strong(expected, slot_id, std::memory_order_acq_rel)) {
108+
return; // Successfully claimed empty spot
109+
}
110+
++tries; // Only count actual CAS attempts
111+
}
112+
}
113+
114+
// Fallback: append if no empty slot found
115+
int pos = _free_list_top.fetch_add(1, std::memory_order_acq_rel);
116+
if (pos < kFreeListSize) {
117+
_free_list[pos].store(slot_id, std::memory_order_release);
118+
} else {
119+
// Free list overflow: ignore
120+
}
79121
}
80122

81123
void ThreadFilter::collect(std::vector<int>& tids) const {

ddprof-lib/src/main/cpp/threadFilter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ class ThreadFilter {
4343
std::vector<std::array<Slot, kChunkSize>> _slots;
4444
std::atomic<SlotID> _next_index;
4545

46+
static constexpr int kFreeListSize = 128;
47+
std::atomic<SlotID> _free_list[kFreeListSize];
48+
std::atomic<int> _free_list_top; // Points to next free slot
49+
4650
mutable std::mutex _slot_mutex;
4751
};
4852

0 commit comments

Comments
 (0)