mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
`AggregateFunctionBitwise` was the only common numeric aggregate without `addBatchSinglePlace`/`addBatchSinglePlaceNotNull` overrides, so with the `-If` combinator it fell back to the generic per-row branch-guarded loop, paying a branch misprediction per row for unpredictable predicates. Accumulate into a local value and apply the flag as a branchless all-ones/all-zeros mask (OR: `acc |= x & m`, AND: `acc &= x | ~m`, XOR: `acc ^= x & m`), writing back to the state once per block. Wide integers build the mask with `memset`, mirroring the `is_over_big_int` path of `sum`. Dispatch with `MULTITARGET_FUNCTION_X86_V4`, like `sum`. Measured (50M rows, 1 thread, unpredictable 50% predicate, server-side query time): `groupBitOrIf`/`groupBitAndIf`/`groupBitXorIf` -74%, `UInt128`/`UInt256` -51..-57%, `Nullable` -31%, `Nullable` + `-If` -59%. No regressions: predictable predicates and the no-`If` path are unchanged.
29 lines
1.6 KiB
XML
29 lines
1.6 KiB
XML
<test>
|
|
<query>SELECT groupBitOrIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT groupBitAndIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT groupBitXorIf(number, rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
|
|
<query>SELECT groupBitOrIf(toUInt32(number), rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
<query>SELECT groupBitOrIf(toUInt8(number), rand32() % 2 = 0) FROM numbers(100000000)</query>
|
|
|
|
<query>SELECT groupBitOrIf(number::UInt128, rand32() % 2 = 0) FROM numbers(50000000)</query>
|
|
<query>SELECT groupBitOrIf(number::UInt256, rand32() % 2 = 0) FROM numbers(50000000)</query>
|
|
<query>SELECT groupBitXorIf(number::UInt256, rand32() % 2 = 0) FROM numbers(50000000)</query>
|
|
|
|
<query>SELECT groupBitOr(number) FROM numbers(100000000)</query>
|
|
<query>SELECT groupBitAnd(number) FROM numbers(100000000)</query>
|
|
<query>SELECT groupBitXor(number) FROM numbers(100000000)</query>
|
|
|
|
<!-- ~20% NULL values, random so the branch predictor doesn't do all the work -->
|
|
<create_query>CREATE TABLE nullint64 (x Nullable(UInt64)) ENGINE = Memory</create_query>
|
|
<fill_query>INSERT INTO nullint64
|
|
SELECT IF(rand() % 5 == 0, NULL::Nullable(UInt64), cityHash64(number)) AS x
|
|
FROM numbers_mt(200000000)
|
|
SETTINGS max_threads = 8
|
|
</fill_query>
|
|
<query>SELECT groupBitOr(x) FROM nullint64</query>
|
|
<query>SELECT groupBitXor(x) FROM nullint64</query>
|
|
<query>SELECT groupBitOrIf(x, rand32() % 2 = 0) FROM nullint64</query>
|
|
<drop_query>DROP TABLE IF EXISTS nullint64</drop_query>
|
|
</test>
|