To save space when sending NDV estimates around the cluster, we compress them using RLE, since they are often sparse. The resulting string has the form CVCVCVCV where C is the count, i.e. the number of times the subsequent V (value) should be repeated in the output string. C is between 0 and 255 inclusive, the count it represents is one more than the absolute value of C (since we never have a 0 co
| 60 | // shorter than the input. Otherwise it is set to false, and the input is returned |
| 61 | // unencoded. |
| 62 | string EncodeNdv(const string& ndv, bool* is_encoded) { |
| 63 | DCHECK_EQ(ndv.size(), AggregateFunctions::DEFAULT_HLL_LEN); |
| 64 | string encoded_ndv(AggregateFunctions::DEFAULT_HLL_LEN, 0); |
| 65 | int idx = 0; |
| 66 | char last = ndv[0]; |
| 67 | |
| 68 | // Keep a count of how many times a value appears in succession. We encode this count as |
| 69 | // a byte 0-255, but the actual count is always one more than the encoded value |
| 70 | // (i.e. in the range 1-256 inclusive). |
| 71 | uint8_t count = 0; |
| 72 | for (int i = 1; i < AggregateFunctions::DEFAULT_HLL_LEN; ++i) { |
| 73 | if (ndv[i] != last || count == numeric_limits<uint8_t>::max()) { |
| 74 | if (idx + 2 > AggregateFunctions::DEFAULT_HLL_LEN) break; |
| 75 | // Write a (count, value) pair to two successive bytes |
| 76 | encoded_ndv[idx++] = count; |
| 77 | count = 0; |
| 78 | encoded_ndv[idx++] = last; |
| 79 | last = ndv[i]; |
| 80 | } else { |
| 81 | ++count; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | // +2 for the remaining two bytes written below |
| 86 | if (idx + 2 > AggregateFunctions::DEFAULT_HLL_LEN) { |
| 87 | *is_encoded = false; |
| 88 | return ndv; |
| 89 | } |
| 90 | |
| 91 | encoded_ndv[idx++] = count; |
| 92 | encoded_ndv[idx++] = last; |
| 93 | |
| 94 | *is_encoded = true; |
| 95 | encoded_ndv.resize(idx); |
| 96 | DCHECK_GT(encoded_ndv.size(), 0); |
| 97 | DCHECK_LE(encoded_ndv.size(), AggregateFunctions::DEFAULT_HLL_LEN); |
| 98 | return encoded_ndv; |
| 99 | } |
| 100 | |
| 101 | string DecodeNdv(const string& ndv, bool is_encoded) { |
| 102 | if (!is_encoded) return ndv; |