Skip to content

Commit 3880153

Browse files
Merge pull request #353 from apache/hll_merge_speed
HLL merge speed improvement
2 parents a360983 + fd19e50 commit 3880153

6 files changed

Lines changed: 46 additions & 36 deletions

File tree

hll/include/Hll4Array-internal.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,9 @@ uint8_t Hll4Array<A>::getSlot(uint32_t slotNo) const {
114114
}
115115

116116
template<typename A>
117-
uint8_t Hll4Array<A>::get_value(uint32_t index) const {
118-
const uint8_t value = getSlot(index);
117+
uint8_t Hll4Array<A>::adjustRawValue(uint32_t slot, uint8_t value) const {
119118
if (value != hll_constants::AUX_TOKEN) return value + this->curMin_;
120-
return auxHashMap_->mustFindValueFor(index);
119+
return auxHashMap_->mustFindValueFor(slot);
121120
}
122121

123122
template<typename A>

hll/include/Hll4Array.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525

2626
namespace datasketches {
2727

28-
template<typename A>
29-
class Hll4Iterator;
30-
3128
template<typename A>
3229
class Hll4Array final : public HllArray<A> {
3330
public:
@@ -41,7 +38,7 @@ class Hll4Array final : public HllArray<A> {
4138

4239
inline uint8_t getSlot(uint32_t slotNo) const;
4340
inline void putSlot(uint32_t slotNo, uint8_t value);
44-
inline uint8_t get_value(uint32_t index) const;
41+
inline uint8_t adjustRawValue(uint32_t index, uint8_t value) const;
4542

4643
virtual uint32_t getUpdatableSerializationBytes() const;
4744
virtual uint32_t getHllByteArrBytes() const;

hll/include/Hll8Array-internal.hpp

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -95,45 +95,51 @@ void Hll8Array<A>::mergeList(const CouponList<A>& src) {
9595
template<typename A>
9696
void Hll8Array<A>::mergeHll(const HllArray<A>& src) {
9797
// at this point src_k >= dst_k
98-
const uint32_t src_k = 1 << src.getLgConfigK();
9998
const uint32_t dst_mask = (1 << this->getLgConfigK()) - 1;
100-
// duplication below is to avoid a virtual method call in a loop
99+
// special treatment below to optimize performance
101100
if (src.getTgtHllType() == target_hll_type::HLL_8) {
102-
for (uint32_t i = 0; i < src_k; i++) {
103-
const uint8_t new_v = static_cast<const Hll8Array<A>&>(src).getSlot(i);
104-
const uint32_t j = i & dst_mask;
105-
const uint8_t old_v = this->hllByteArr_[j];
106-
if (new_v > old_v) {
107-
this->hllByteArr_[j] = new_v;
108-
this->hipAndKxQIncrementalUpdate(old_v, new_v);
109-
this->numAtCurMin_ -= old_v == 0;
110-
}
101+
uint32_t i = 0;
102+
for (const auto value: src.getHllArray()) {
103+
processValue(i++, dst_mask, value);
111104
}
112105
} else if (src.getTgtHllType() == target_hll_type::HLL_6) {
113-
for (uint32_t i = 0; i < src_k; i++) {
114-
const uint8_t new_v = static_cast<const Hll6Array<A>&>(src).getSlot(i);
115-
const uint32_t j = i & dst_mask;
116-
const uint8_t old_v = this->hllByteArr_[j];
117-
if (new_v > old_v) {
118-
this->hllByteArr_[j] = new_v;
119-
this->hipAndKxQIncrementalUpdate(old_v, new_v);
120-
this->numAtCurMin_ -= old_v == 0;
121-
}
106+
const uint32_t src_k = 1 << src.getLgConfigK();
107+
uint32_t i = 0;
108+
const uint8_t* ptr = src.getHllArray().data();
109+
while (i < src_k) {
110+
uint8_t value = *ptr & 0x3f;
111+
processValue(i++, dst_mask, value);
112+
value = *ptr++ >> 6;
113+
value |= (*ptr & 0x0f) << 2;
114+
processValue(i++, dst_mask, value);
115+
value = *ptr++ >> 4;
116+
value |= (*ptr & 3) << 4;
117+
processValue(i++, dst_mask, value);
118+
value = *ptr++ >> 2;
119+
processValue(i++, dst_mask, value);
122120
}
123121
} else { // HLL_4
124-
for (uint32_t i = 0; i < src_k; i++) {
125-
const uint8_t new_v = static_cast<const Hll4Array<A>&>(src).get_value(i);
126-
const uint32_t j = i & dst_mask;
127-
const uint8_t old_v = this->hllByteArr_[j];
128-
if (new_v > old_v) {
129-
this->hllByteArr_[j] = new_v;
130-
this->hipAndKxQIncrementalUpdate(old_v, new_v);
131-
this->numAtCurMin_ -= old_v == 0;
132-
}
122+
const auto& src4 = static_cast<const Hll4Array<A>&>(src);
123+
uint32_t i = 0;
124+
for (const auto byte: src.getHllArray()) {
125+
processValue(i, dst_mask, src4.adjustRawValue(i, byte & hll_constants::loNibbleMask));
126+
++i;
127+
processValue(i, dst_mask, src4.adjustRawValue(i, byte >> 4));
128+
++i;
133129
}
134130
}
135131
}
136132

133+
template<typename A>
134+
void Hll8Array<A>::processValue(uint32_t slot, uint32_t mask, uint8_t new_val) {
135+
const uint8_t old_val = this->hllByteArr_[slot & mask];
136+
if (new_val > old_val) {
137+
this->hllByteArr_[slot & mask] = new_val;
138+
this->hipAndKxQIncrementalUpdate(old_val, new_val);
139+
this->numAtCurMin_ -= old_val == 0;
140+
}
141+
}
142+
137143
}
138144

139145
#endif // _HLL8ARRAY_INTERNAL_HPP_

hll/include/Hll8Array.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Hll8Array final : public HllArray<A> {
4848

4949
private:
5050
inline void internalCouponUpdate(uint32_t coupon);
51+
inline void processValue(uint32_t slot, uint32_t mask, uint8_t new_val);
5152
};
5253

5354
}

hll/include/HllArray-internal.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@ AuxHashMap<A>* HllArray<A>::getAuxHashMap() const {
512512
return nullptr;
513513
}
514514

515+
template<typename A>
516+
const vector_u8<A>& HllArray<A>::getHllArray() const {
517+
return hllByteArr_;
518+
}
519+
515520
template<typename A>
516521
void HllArray<A>::hipAndKxQIncrementalUpdate(uint8_t oldValue, uint8_t newValue) {
517522
const uint32_t configK = 1 << this->getLgConfigK();

hll/include/HllArray.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ class HllArray : public HllSketchImpl<A> {
9292

9393
virtual A getAllocator() const;
9494

95+
const vector_u8<A>& getHllArray() const;
96+
9597
protected:
9698
void hipAndKxQIncrementalUpdate(uint8_t oldValue, uint8_t newValue);
9799
double getHllBitMapEstimate() const;

0 commit comments

Comments
 (0)