Skip to content

Commit 78cfaf5

Browse files
committed
refactor(dxmt): improve binding bitset iteration performance
1 parent e1d5181 commit 78cfaf5

2 files changed

Lines changed: 30 additions & 19 deletions

File tree

src/dxmt/dxmt_binding_set.hpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,22 @@ template <typename Element, size_t NumElements> class BindingSet {
5959
}
6060

6161
constexpr bool
62-
any_dirty_masked(uint16_t mask) noexcept {
62+
any_dirty_masked(uint16_t mask) const noexcept {
6363
return (dirty.qword(0) & (uint64_t)mask) != 0;
6464
}
6565

6666
constexpr bool
67-
any_dirty_masked(uint64_t mask) noexcept {
67+
any_dirty_masked(uint64_t mask) const noexcept {
6868
return (dirty.qword(0) & mask) != 0;
6969
}
7070

7171
constexpr bool
72-
any_dirty_masked(uint64_t mask_hi, uint64_t mask_lo) noexcept {
72+
any_dirty_masked(uint64_t mask_hi, uint64_t mask_lo) const noexcept {
7373
return ((dirty.qword(0) & mask_lo) | (dirty.qword(1) & mask_hi)) != 0;
7474
}
7575

7676
constexpr bool
77-
all_bound_masked(uint32_t mask) noexcept {
77+
all_bound_masked(uint32_t mask) const noexcept {
7878
return (bound.qword(0) & mask) == mask;
7979
}
8080

@@ -84,9 +84,9 @@ template <typename Element, size_t NumElements> class BindingSet {
8484
}
8585

8686
constexpr uint32_t
87-
max_binding_64() noexcept {
88-
auto qword = dirty.qword(0);
89-
return qword == 0 ? 0 : 64 - __builtin_clzll(qword);
87+
max_binding_64() const noexcept {
88+
uint64_t qword = dirty.qword(0);
89+
return 64u - bit::tzcnt(qword);
9090
}
9191

9292
inline void
@@ -157,13 +157,23 @@ template <typename Element, size_t NumElements> class BindingSet {
157157

158158
class bound_iterator {
159159
const BindingSet &binding_set;
160+
const bit::bitset<NumElements> &bits;
160161
size_t current;
161162

162163
void
163164
advance_to_next() {
164-
while (current < NumElements && !binding_set.bound.get(current)) {
165-
++current;
165+
while (current < NumElements) {
166+
auto qword_index = current / 64;
167+
auto tz = bit::tzcnt(uint64_t(bits.qword(qword_index) & ~((1ull << (current % 64)) - 1ull)));
168+
if (tz < 64) {
169+
current = qword_index * 64 + tz;
170+
return;
171+
}
172+
current = (qword_index + 1) * 64;
173+
continue;
166174
}
175+
// just in case, clamp it
176+
current = NumElements;
167177
}
168178

169179
public:
@@ -173,7 +183,10 @@ template <typename Element, size_t NumElements> class BindingSet {
173183
using pointer = void;
174184
using reference = std::pair<size_t, const Element &>;
175185

176-
bound_iterator(const BindingSet &set, size_t start) : binding_set(set), current(start) {
186+
bound_iterator(const BindingSet &set, const bit::bitset<NumElements> &bits, size_t start) :
187+
binding_set(set),
188+
bits(bits),
189+
current(start) {
177190
advance_to_next();
178191
}
179192

@@ -197,22 +210,18 @@ template <typename Element, size_t NumElements> class BindingSet {
197210
}
198211

199212
bool
200-
operator==(const bound_iterator &other) const {
201-
return current == other.current;
202-
}
203-
bool
204-
operator!=(const bound_iterator &other) const {
205-
return !(*this == other);
213+
operator!=(uint64_t index) const {
214+
return current != index;
206215
}
207216
};
208217

209218
bound_iterator
210219
begin() const {
211-
return bound_iterator(*this, 0);
220+
return bound_iterator(*this, bound, 0);
212221
}
213-
bound_iterator
222+
uint64_t
214223
end() const {
215-
return bound_iterator(*this, NumElements);
224+
return NumElements;
216225
}
217226
};
218227
} // namespace dxmt

src/util/util_bit.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,8 @@ template <size_t Bits> class bitset {
327327

328328
constexpr uint64_t &qword(uint64_t idx) { return m_qwords[idx]; }
329329

330+
constexpr uint64_t qword(uint64_t idx) const { return m_qwords[idx]; }
331+
330332
constexpr size_t bitCount() { return Bits; }
331333

332334
constexpr size_t qwordCount() { return Qwords; }

0 commit comments

Comments
 (0)