Coverage Report

Created: 2026-09-16 23:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/partitioner/partitioner.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <algorithm>
21
22
#include "core/block/block.h"
23
#include "exprs/vexpr.h"
24
#include "exprs/vexpr_context.h"
25
26
namespace doris {
27
28
class PartitionerBase {
29
public:
30
    using HashValType = uint32_t;
31
32
61
    PartitionerBase(HashValType partition_count) : _partition_count(partition_count) {}
33
61
    virtual ~PartitionerBase() = default;
34
35
    virtual Status init(const std::vector<TExpr>& texprs) = 0;
36
37
    virtual Status prepare(RuntimeState* state, const RowDescriptor& row_desc) = 0;
38
39
    virtual Status open(RuntimeState* state) = 0;
40
41
    virtual Status close(RuntimeState* state) = 0;
42
43
    virtual Status do_partitioning(RuntimeState* state, Block* block) const = 0;
44
45
    virtual const std::vector<HashValType>& get_channel_ids() const = 0;
46
47
    virtual Status clone(RuntimeState* state, std::unique_ptr<PartitionerBase>& partitioner) = 0;
48
49
    // use _partition_count as invalid sentinel value. since modulo operation result is [0, partition_count-1]
50
6
    HashValType partition_count() const { return _partition_count; }
51
    // use a individual function to highlight its special meaning
52
4
    HashValType invalid_sentinel() const { return partition_count(); }
53
54
protected:
55
    const HashValType _partition_count;
56
};
57
58
enum class ShuffleHashMethod {
59
    CRC32,
60
    CRC32C,
61
};
62
63
class PartitionFunction {
64
public:
65
    using HashValType = PartitionerBase::HashValType;
66
67
11
    virtual ~PartitionFunction() = default;
68
69
    virtual Status init(const std::vector<TExpr>& texprs) = 0;
70
71
    virtual Status prepare(RuntimeState* state, const RowDescriptor& row_desc) = 0;
72
73
    virtual Status open(RuntimeState* state) = 0;
74
75
    virtual Status close(RuntimeState* state) = 0;
76
77
    virtual Status get_partitions(RuntimeState* state, Block* block, size_t partition_count,
78
                                  std::vector<HashValType>& partitions) const = 0;
79
80
    virtual HashValType partition_count() const = 0;
81
82
    virtual Status clone(RuntimeState* state,
83
                         std::unique_ptr<PartitionFunction>& function) const = 0;
84
};
85
86
// Adapts the standard Doris expression hash partitioner to the composable
87
// PartitionFunction interface used by sink routing.
88
class HashPartitionFunction final : public PartitionFunction {
89
public:
90
    HashPartitionFunction(HashValType partition_count, ShuffleHashMethod hash_method);
91
92
    Status init(const std::vector<TExpr>& texprs) override;
93
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override;
94
    Status open(RuntimeState* state) override;
95
    Status close(RuntimeState* state) override;
96
    Status get_partitions(RuntimeState* state, Block* block, size_t partition_count,
97
                          std::vector<HashValType>& partitions) const override;
98
0
    HashValType partition_count() const override { return _partition_count; }
99
    Status clone(RuntimeState* state, std::unique_ptr<PartitionFunction>& function) const override;
100
101
private:
102
    HashValType _partition_count;
103
    ShuffleHashMethod _hash_method;
104
    std::unique_ptr<PartitionerBase> _partitioner;
105
};
106
107
template <typename ChannelIds>
108
class Crc32HashPartitioner : public PartitionerBase {
109
public:
110
41
    Crc32HashPartitioner(int partition_count) : PartitionerBase(partition_count) {}
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEEC2Ei
Line
Count
Source
110
7
    Crc32HashPartitioner(int partition_count) : PartitionerBase(partition_count) {}
_ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEEC2Ei
Line
Count
Source
110
23
    Crc32HashPartitioner(int partition_count) : PartitionerBase(partition_count) {}
_ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEEC2Ei
Line
Count
Source
110
10
    Crc32HashPartitioner(int partition_count) : PartitionerBase(partition_count) {}
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEEC2Ei
Line
Count
Source
110
1
    Crc32HashPartitioner(int partition_count) : PartitionerBase(partition_count) {}
111
41
    ~Crc32HashPartitioner() override = default;
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEED2Ev
Line
Count
Source
111
1
    ~Crc32HashPartitioner() override = default;
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEED2Ev
Line
Count
Source
111
7
    ~Crc32HashPartitioner() override = default;
_ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEED2Ev
Line
Count
Source
111
23
    ~Crc32HashPartitioner() override = default;
_ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEED2Ev
Line
Count
Source
111
10
    ~Crc32HashPartitioner() override = default;
112
113
26
    Status init(const std::vector<TExpr>& texprs) override {
114
26
        return VExpr::create_expr_trees(texprs, _partition_expr_ctxs);
115
26
    }
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE4initERKSt6vectorINS_5TExprESaIS4_EE
Line
Count
Source
113
1
    Status init(const std::vector<TExpr>& texprs) override {
114
1
        return VExpr::create_expr_trees(texprs, _partition_expr_ctxs);
115
1
    }
_ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE4initERKSt6vectorINS_5TExprESaIS4_EE
Line
Count
Source
113
18
    Status init(const std::vector<TExpr>& texprs) override {
114
18
        return VExpr::create_expr_trees(texprs, _partition_expr_ctxs);
115
18
    }
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE4initERKSt6vectorINS_5TExprESaIS4_EE
Line
Count
Source
113
1
    Status init(const std::vector<TExpr>& texprs) override {
114
1
        return VExpr::create_expr_trees(texprs, _partition_expr_ctxs);
115
1
    }
_ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE4initERKSt6vectorINS_5TExprESaIS4_EE
Line
Count
Source
113
6
    Status init(const std::vector<TExpr>& texprs) override {
114
6
        return VExpr::create_expr_trees(texprs, _partition_expr_ctxs);
115
6
    }
116
117
23
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override {
118
23
        return VExpr::prepare(_partition_expr_ctxs, state, row_desc);
119
23
    }
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE7prepareEPNS_12RuntimeStateERKNS_13RowDescriptorE
Line
Count
Source
117
1
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override {
118
1
        return VExpr::prepare(_partition_expr_ctxs, state, row_desc);
119
1
    }
_ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE7prepareEPNS_12RuntimeStateERKNS_13RowDescriptorE
Line
Count
Source
117
15
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override {
118
15
        return VExpr::prepare(_partition_expr_ctxs, state, row_desc);
119
15
    }
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE7prepareEPNS_12RuntimeStateERKNS_13RowDescriptorE
Line
Count
Source
117
1
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override {
118
1
        return VExpr::prepare(_partition_expr_ctxs, state, row_desc);
119
1
    }
_ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE7prepareEPNS_12RuntimeStateERKNS_13RowDescriptorE
Line
Count
Source
117
6
    Status prepare(RuntimeState* state, const RowDescriptor& row_desc) override {
118
6
        return VExpr::prepare(_partition_expr_ctxs, state, row_desc);
119
6
    }
120
121
14
    Status open(RuntimeState* state) override { return VExpr::open(_partition_expr_ctxs, state); }
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE4openEPNS_12RuntimeStateE
Line
Count
Source
121
1
    Status open(RuntimeState* state) override { return VExpr::open(_partition_expr_ctxs, state); }
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE4openEPNS_12RuntimeStateE
Line
Count
Source
121
1
    Status open(RuntimeState* state) override { return VExpr::open(_partition_expr_ctxs, state); }
_ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE4openEPNS_12RuntimeStateE
Line
Count
Source
121
6
    Status open(RuntimeState* state) override { return VExpr::open(_partition_expr_ctxs, state); }
_ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE4openEPNS_12RuntimeStateE
Line
Count
Source
121
6
    Status open(RuntimeState* state) override { return VExpr::open(_partition_expr_ctxs, state); }
122
123
2
    Status close(RuntimeState* state) override { return Status::OK(); }
_ZN5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE5closeEPNS_12RuntimeStateE
Line
Count
Source
123
1
    Status close(RuntimeState* state) override { return Status::OK(); }
_ZN5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE5closeEPNS_12RuntimeStateE
Line
Count
Source
123
1
    Status close(RuntimeState* state) override { return Status::OK(); }
Unexecuted instantiation: _ZN5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE5closeEPNS_12RuntimeStateE
Unexecuted instantiation: _ZN5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE5closeEPNS_12RuntimeStateE
124
125
    Status do_partitioning(RuntimeState* state, Block* block) const override;
126
127
40
    const std::vector<HashValType>& get_channel_ids() const override { return _hash_vals; }
_ZNK5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE15get_channel_idsEv
Line
Count
Source
127
1
    const std::vector<HashValType>& get_channel_ids() const override { return _hash_vals; }
_ZNK5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE15get_channel_idsEv
Line
Count
Source
127
23
    const std::vector<HashValType>& get_channel_ids() const override { return _hash_vals; }
_ZNK5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE15get_channel_idsEv
Line
Count
Source
127
8
    const std::vector<HashValType>& get_channel_ids() const override { return _hash_vals; }
_ZNK5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE15get_channel_idsEv
Line
Count
Source
127
8
    const std::vector<HashValType>& get_channel_ids() const override { return _hash_vals; }
128
129
    Status clone(RuntimeState* state, std::unique_ptr<PartitionerBase>& partitioner) override;
130
131
protected:
132
40
    Status _get_partition_column_result(Block* block, std::vector<int>& result) const {
133
40
        int counter = 0;
134
40
        for (auto ctx : _partition_expr_ctxs) {
135
39
            RETURN_IF_ERROR(ctx->execute(block, &result[counter++]));
136
39
        }
137
40
        return Status::OK();
138
40
    }
_ZNK5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE28_get_partition_column_resultEPNS_5BlockERSt6vectorIiSaIiEE
Line
Count
Source
132
23
    Status _get_partition_column_result(Block* block, std::vector<int>& result) const {
133
23
        int counter = 0;
134
23
        for (auto ctx : _partition_expr_ctxs) {
135
22
            RETURN_IF_ERROR(ctx->execute(block, &result[counter++]));
136
22
        }
137
23
        return Status::OK();
138
23
    }
_ZNK5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE28_get_partition_column_resultEPNS_5BlockERSt6vectorIiSaIiEE
Line
Count
Source
132
8
    Status _get_partition_column_result(Block* block, std::vector<int>& result) const {
133
8
        int counter = 0;
134
8
        for (auto ctx : _partition_expr_ctxs) {
135
8
            RETURN_IF_ERROR(ctx->execute(block, &result[counter++]));
136
8
        }
137
8
        return Status::OK();
138
8
    }
_ZNK5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE28_get_partition_column_resultEPNS_5BlockERSt6vectorIiSaIiEE
Line
Count
Source
132
8
    Status _get_partition_column_result(Block* block, std::vector<int>& result) const {
133
8
        int counter = 0;
134
8
        for (auto ctx : _partition_expr_ctxs) {
135
8
            RETURN_IF_ERROR(ctx->execute(block, &result[counter++]));
136
8
        }
137
8
        return Status::OK();
138
8
    }
_ZNK5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE28_get_partition_column_resultEPNS_5BlockERSt6vectorIiSaIiEE
Line
Count
Source
132
1
    Status _get_partition_column_result(Block* block, std::vector<int>& result) const {
133
1
        int counter = 0;
134
1
        for (auto ctx : _partition_expr_ctxs) {
135
1
            RETURN_IF_ERROR(ctx->execute(block, &result[counter++]));
136
1
        }
137
1
        return Status::OK();
138
1
    }
139
140
9
    Status _clone_expr_ctxs(RuntimeState* state, VExprContextSPtrs& new_partition_expr_ctxs) const {
141
9
        new_partition_expr_ctxs.resize(_partition_expr_ctxs.size());
142
18
        for (size_t i = 0; i < _partition_expr_ctxs.size(); i++) {
143
9
            RETURN_IF_ERROR(_partition_expr_ctxs[i]->clone(state, new_partition_expr_ctxs[i]));
144
9
        }
145
9
        return Status::OK();
146
9
    }
Unexecuted instantiation: _ZNK5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE16_clone_expr_ctxsEPNS_12RuntimeStateERSt6vectorISt10shared_ptrINS_12VExprContextEESaIS8_EE
_ZNK5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE16_clone_expr_ctxsEPNS_12RuntimeStateERSt6vectorISt10shared_ptrINS_12VExprContextEESaIS8_EE
Line
Count
Source
140
5
    Status _clone_expr_ctxs(RuntimeState* state, VExprContextSPtrs& new_partition_expr_ctxs) const {
141
5
        new_partition_expr_ctxs.resize(_partition_expr_ctxs.size());
142
10
        for (size_t i = 0; i < _partition_expr_ctxs.size(); i++) {
143
5
            RETURN_IF_ERROR(_partition_expr_ctxs[i]->clone(state, new_partition_expr_ctxs[i]));
144
5
        }
145
5
        return Status::OK();
146
5
    }
_ZNK5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE16_clone_expr_ctxsEPNS_12RuntimeStateERSt6vectorISt10shared_ptrINS_12VExprContextEESaIS8_EE
Line
Count
Source
140
4
    Status _clone_expr_ctxs(RuntimeState* state, VExprContextSPtrs& new_partition_expr_ctxs) const {
141
4
        new_partition_expr_ctxs.resize(_partition_expr_ctxs.size());
142
8
        for (size_t i = 0; i < _partition_expr_ctxs.size(); i++) {
143
4
            RETURN_IF_ERROR(_partition_expr_ctxs[i]->clone(state, new_partition_expr_ctxs[i]));
144
4
        }
145
4
        return Status::OK();
146
4
    }
Unexecuted instantiation: _ZNK5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE16_clone_expr_ctxsEPNS_12RuntimeStateERSt6vectorISt10shared_ptrINS_12VExprContextEESaIS8_EE
147
148
    virtual void _do_hash(const ColumnPtr& column, HashValType* __restrict result, int idx) const;
149
39
    virtual void _initialize_hash_vals(size_t rows) const {
150
39
        _hash_vals.resize(rows);
151
39
        std::ranges::fill(_hash_vals, 0);
152
39
    }
Unexecuted instantiation: _ZNK5doris20Crc32HashPartitionerINS_15ShiftChannelIdsEE21_initialize_hash_valsEm
_ZNK5doris20Crc32HashPartitionerINS_17ShuffleChannelIdsEE21_initialize_hash_valsEm
Line
Count
Source
149
23
    virtual void _initialize_hash_vals(size_t rows) const {
150
23
        _hash_vals.resize(rows);
151
23
        std::ranges::fill(_hash_vals, 0);
152
23
    }
_ZNK5doris20Crc32HashPartitionerINS_24SpillPartitionChannelIdsEE21_initialize_hash_valsEm
Line
Count
Source
149
8
    virtual void _initialize_hash_vals(size_t rows) const {
150
8
        _hash_vals.resize(rows);
151
8
        std::ranges::fill(_hash_vals, 0);
152
8
    }
_ZNK5doris20Crc32HashPartitionerINS_26SpillRePartitionChannelIdsEE21_initialize_hash_valsEm
Line
Count
Source
149
8
    virtual void _initialize_hash_vals(size_t rows) const {
150
8
        _hash_vals.resize(rows);
151
8
        std::ranges::fill(_hash_vals, 0);
152
8
    }
153
154
    VExprContextSPtrs _partition_expr_ctxs;
155
    mutable std::vector<HashValType> _hash_vals;
156
};
157
158
struct ShuffleChannelIds {
159
    using HashValType = PartitionerBase::HashValType;
160
217
    HashValType operator()(HashValType l, size_t r) { return l % r; }
161
};
162
163
struct SpillPartitionChannelIds {
164
    using HashValType = PartitionerBase::HashValType;
165
    // Default spill partition mapping used by level-0 partitioning:
166
    // rotate hash bits and apply modulo to get a channel id directly.
167
3.14M
    HashValType operator()(HashValType l, size_t r) { return ((l >> 16) | (l << 16)) % r; }
168
};
169
170
struct SpillRePartitionChannelIds {
171
    using HashValType = PartitionerBase::HashValType;
172
173
    // Repartition mode: return the raw hash value without modulo.
174
    // The caller (SpillRepartitioner) will apply level-aware hash mixing and
175
    // final channel mapping, so repartition behavior can vary by level.
176
20
    HashValType operator()(HashValType l, size_t /*r*/) { return l; }
177
};
178
179
655
static inline PartitionerBase::HashValType crc32c_shuffle_mix(PartitionerBase::HashValType h) {
180
    // Step 1: fold high entropy into low bits
181
655
    h ^= h >> 16;
182
    // Step 2: odd multiplicative scramble (cheap avalanche)
183
655
    h *= 0xA5B35705U;
184
    // Step 3: final fold to break remaining linearity
185
655
    h ^= h >> 13;
186
655
    return h;
187
655
}
Unexecuted instantiation: merge_partitioner_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: exchange_sink_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: exchange_writer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: agg_operator_group_by_limit_opt_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: agg_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: analytic_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: assert_nums_rows_operator.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: datagen_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: distinct_streaming_aggregation_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: empty_set_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: exchange_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: exchange_source_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: file_scan_operator_adbc_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: hash_join_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: hashjoin_build_sink_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: hashjoin_probe_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: join_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: local_merge_sort_source_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: materialization_shared_state_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: nested_loop_join_build_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: olap_scan_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: operator_projection_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partition_sort_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_aggregation_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_aggregation_source_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_aggregation_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_hash_join_probe_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_hash_join_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_hash_join_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: query_cache_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: repeat_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: scan_normalize_predicate_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: set_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: sort_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spill_sort_sink_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spill_sort_source_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spill_sort_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spillable_operator_test_helper.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: streaming_agg_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: table_function_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: union_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: external_table_sink_hash_partitioner_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: local_exchanger_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: multi_cast_data_streamer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: pipeline_task_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: pipeline_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: query_cache_fragment_context_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vdata_stream_recvr_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: rowid_fetcher_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_consumer_helper_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_consumer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_expr_sampling_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_merger_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_mgr_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_producer_helper_cross_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_producer_helper_set_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_producer_helper_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_filter_producer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: sync_size_callback_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: file_scanner_v2_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: scan_operator_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: scanner_context_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: scanner_late_arrival_rf_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vfile_scanner_exception_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: tablet_sink_hash_partitioner_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vrow_distribution_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vtablet_writer_v2_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vhive_partition_writer_report_lifecycle_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: orc_convert_to_orc_literal_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: orc_read_lines.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: parquet_read_lines.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: wal_manager_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: cached_remote_file_reader_peer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: memtable_flush_executor_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: cloud_group_rowset_builder_writer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: group_rowset_builder_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: group_rowset_writer_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: memory_reclamation_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: runtime_predicate_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: workload_sched_policy_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: historical_row_fetcher_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: key_probe_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: segment_flusher_format_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: engine_storage_migration_task_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: historical_row_retriever_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: snapshot_manager_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: fixed_partial_update_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: flexible_partial_update_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: row_binlog_derive_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: validate_stage_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: variant_rowstore_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: profile_spec_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spill_file_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: spill_repartitioner_test.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
unity_14_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Line
Count
Source
179
650
static inline PartitionerBase::HashValType crc32c_shuffle_mix(PartitionerBase::HashValType h) {
180
    // Step 1: fold high entropy into low bits
181
650
    h ^= h >> 16;
182
    // Step 2: odd multiplicative scramble (cheap avalanche)
183
650
    h *= 0xA5B35705U;
184
    // Step 3: final fold to break remaining linearity
185
650
    h ^= h >> 13;
186
650
    return h;
187
650
}
Unexecuted instantiation: unity_11_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_10_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_9_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
unity_8_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Line
Count
Source
179
5
static inline PartitionerBase::HashValType crc32c_shuffle_mix(PartitionerBase::HashValType h) {
180
    // Step 1: fold high entropy into low bits
181
5
    h ^= h >> 16;
182
    // Step 2: odd multiplicative scramble (cheap avalanche)
183
5
    h *= 0xA5B35705U;
184
    // Step 3: final fold to break remaining linearity
185
5
    h ^= h >> 13;
186
5
    return h;
187
5
}
Unexecuted instantiation: unity_7_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_6_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_5_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_4_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_3_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_2_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_1_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_0_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: hashjoin_build_sink.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: join_build_sink_operator.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: operator.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: partitioned_aggregation_sink_operator.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: scan_operator.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vfile_result_writer.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: unity_29_cxx.cxx:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: vparquet_reader.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: iceberg_partition_function.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
Unexecuted instantiation: merge_partitioner.cpp:_ZN5dorisL18crc32c_shuffle_mixEj
188
189
// use high 16 bits as channel id to avoid conflict with crc32c hash table
190
// shuffle hash function same with crc32c hash table(eg join hash table) will lead bad performance
191
// hash table offten use low 16 bits as bucket index, so we shift 16 bits to high bits to avoid conflict
192
struct ShiftChannelIds {
193
    using HashValType = PartitionerBase::HashValType;
194
5
    HashValType operator()(HashValType l, size_t r) { return crc32c_shuffle_mix(l) % r; }
195
};
196
197
class Crc32CHashPartitioner : public Crc32HashPartitioner<ShiftChannelIds> {
198
public:
199
    Crc32CHashPartitioner(int partition_count)
200
1
            : Crc32HashPartitioner<ShiftChannelIds>(partition_count) {}
201
202
    Status clone(RuntimeState* state, std::unique_ptr<PartitionerBase>& partitioner) override;
203
204
private:
205
    void _do_hash(const ColumnPtr& column, HashValType* __restrict result, int idx) const override;
206
207
1
    void _initialize_hash_vals(size_t rows) const override {
208
1
        _hash_vals.resize(rows);
209
        // use golden ratio to initialize hash values to avoid collision with hash table's hash function
210
1
        constexpr HashValType CRC32C_SHUFFLE_SEED = 0x9E3779B9U;
211
1
        std::ranges::fill(_hash_vals, CRC32C_SHUFFLE_SEED);
212
1
    }
213
};
214
215
/// Instantiated once in partitioner.cpp; suppresses per-TU implicit instantiation.
216
extern template class Crc32HashPartitioner<ShuffleChannelIds>;
217
extern template class Crc32HashPartitioner<SpillPartitionChannelIds>;
218
extern template class Crc32HashPartitioner<SpillRePartitionChannelIds>;
219
220
} // namespace doris