Skip to content

Commit 1e4bdda

Browse files
committed
update
1 parent 4e79388 commit 1e4bdda

File tree

3 files changed

+49
-39
lines changed

3 files changed

+49
-39
lines changed

be/src/pipeline/exec/aggregation_sink_operator.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -649,12 +649,10 @@ bool AggSinkLocalState::_emplace_into_hash_table_limit(vectorized::AggregateData
649649
};
650650

651651
SCOPED_TIMER(_hash_table_emplace_timer);
652-
vectorized::lazy_emplace_batch(agg_method, state, num_rows, creator,
653-
creator_for_null_key,
654-
[&](uint32_t row, auto& mapped) {
655-
i = row;
656-
places[row] = mapped;
657-
});
652+
vectorized::lazy_emplace_batch(
653+
agg_method, state, num_rows, creator, creator_for_null_key,
654+
[&](uint32_t row) { i = row; },
655+
[&](uint32_t row, auto& mapped) { places[row] = mapped; });
658656
COUNTER_UPDATE(_hash_table_input_counter, num_rows);
659657
return true;
660658
}

be/src/pipeline/exec/streaming_aggregation_operator.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -728,12 +728,10 @@ bool StreamingAggLocalState::_emplace_into_hash_table_limit(vectorized::Aggregat
728728
};
729729

730730
SCOPED_TIMER(_hash_table_emplace_timer);
731-
vectorized::lazy_emplace_batch(agg_method, state, num_rows, creator,
732-
creator_for_null_key,
733-
[&](uint32_t row, auto& mapped) {
734-
i = row;
735-
places[row] = mapped;
736-
});
731+
vectorized::lazy_emplace_batch(
732+
agg_method, state, num_rows, creator, creator_for_null_key,
733+
[&](uint32_t row) { i = row; },
734+
[&](uint32_t row, auto& mapped) { places[row] = mapped; });
737735
COUNTER_UPDATE(_hash_table_input_counter, num_rows);
738736
return true;
739737
}

be/src/vec/common/hash_table/hash_map_context.h

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -112,22 +112,21 @@ struct MethodBaseInner {
112112
}
113113

114114
template <bool read>
115-
ALWAYS_INLINE void prefetch(size_t i) {
115+
void prefetch(size_t i) {
116116
if (LIKELY(i + HASH_MAP_PREFETCH_DIST < hash_values.size())) {
117117
hash_table->template prefetch<read>(keys[i + HASH_MAP_PREFETCH_DIST],
118118
hash_values[i + HASH_MAP_PREFETCH_DIST]);
119119
}
120120
}
121121

122122
template <typename State>
123-
ALWAYS_INLINE auto find(State& state, size_t i) {
123+
auto find(State& state, size_t i) {
124124
prefetch<true>(i);
125125
return state.find_key_with_hash(*hash_table, i, keys[i], hash_values[i]);
126126
}
127127

128128
template <typename State, typename F, typename FF>
129-
ALWAYS_INLINE auto lazy_emplace(State& state, size_t i, F&& creator,
130-
FF&& creator_for_null_key) {
129+
auto lazy_emplace(State& state, size_t i, F&& creator, FF&& creator_for_null_key) {
131130
prefetch<false>(i);
132131
return state.lazy_emplace_key(*hash_table, i, keys[i], hash_values[i], creator,
133132
creator_for_null_key);
@@ -432,7 +431,7 @@ struct IsNullableStringHashMap<DataWithNullKey<StringHashMap<Mapped, Allocator>>
432431

433432
/// Helper: get the underlying StringHashTable from a hash table (handles DataWithNullKey wrapper).
434433
template <typename HashMap>
435-
ALWAYS_INLINE auto& get_string_hash_table(HashMap& data) {
434+
auto& get_string_hash_table(HashMap& data) {
436435
return data;
437436
}
438437

@@ -441,7 +440,7 @@ ALWAYS_INLINE auto& get_string_hash_table(HashMap& data) {
441440
/// Returns a pair: (converted_key, needs_copy).
442441
/// For groups 0 and 5, the key must be a non-const copy (lazy_emplace_if_zero takes Key&).
443442
template <int GroupIdx>
444-
ALWAYS_INLINE auto convert_key_for_submap(const StringRef& origin) {
443+
auto convert_key_for_submap(const StringRef& origin) {
445444
if constexpr (GroupIdx == 0) {
446445
return StringRef(origin); // copy — m0 needs non-const Key&
447446
} else if constexpr (GroupIdx == 1) {
@@ -459,7 +458,7 @@ ALWAYS_INLINE auto convert_key_for_submap(const StringRef& origin) {
459458

460459
/// Hash value to use for a given group. Group 0 (empty string) always uses hash=0.
461460
template <int GroupIdx, typename HashValues>
462-
ALWAYS_INLINE size_t hash_for_group(const HashValues& hash_values, uint32_t row) {
461+
size_t hash_for_group(const HashValues& hash_values, uint32_t row) {
463462
if constexpr (GroupIdx == 0) {
464463
return 0;
465464
} else {
@@ -474,13 +473,14 @@ static constexpr bool group_needs_prefetch = (GroupIdx != 0);
474473

475474
/// Process one sub-table group for emplace with result_handler.
476475
/// Handles nullable null-key check, prefetch, key conversion, and emplace.
476+
/// pre_handler(row) is called before each emplace, allowing callers to set per-row state
477+
/// (e.g., current row index used inside creator lambdas).
477478
template <int GroupIdx, bool is_nullable, typename Submap, typename HashMethodType, typename State,
478-
typename HashMap, typename F, typename FF, typename ResultHandler>
479-
ALWAYS_INLINE void process_submap_emplace(Submap& submap, const uint32_t* indices, size_t count,
480-
HashMethodType& agg_method, State& state,
481-
HashMap& hash_table, F&& creator,
482-
FF&& creator_for_null_key,
483-
ResultHandler&& result_handler) {
479+
typename HashMap, typename F, typename FF, typename PreHandler, typename ResultHandler>
480+
void process_submap_emplace(Submap& submap, const uint32_t* indices, size_t count,
481+
HashMethodType& agg_method, State& state, HashMap& hash_table,
482+
F&& creator, FF&& creator_for_null_key, PreHandler&& pre_handler,
483+
ResultHandler&& result_handler) {
484484
using Mapped = typename HashMethodType::Mapped;
485485
for (size_t j = 0; j < count; j++) {
486486
if constexpr (group_needs_prefetch<GroupIdx>) {
@@ -490,6 +490,7 @@ ALWAYS_INLINE void process_submap_emplace(Submap& submap, const uint32_t* indice
490490
}
491491
}
492492
uint32_t row = indices[j];
493+
pre_handler(row);
493494
if constexpr (is_nullable) {
494495
if (state.key_column->is_null_at(row)) {
495496
bool has_null_key = hash_table.has_null_key_data();
@@ -524,11 +525,9 @@ ALWAYS_INLINE void process_submap_emplace(Submap& submap, const uint32_t* indice
524525
/// pre_handler(row) is called before each emplace.
525526
template <int GroupIdx, bool is_nullable, typename Submap, typename HashMethodType, typename State,
526527
typename HashMap, typename F, typename FF, typename PreHandler>
527-
ALWAYS_INLINE void process_submap_emplace_void(Submap& submap, const uint32_t* indices,
528-
size_t count, HashMethodType& agg_method,
529-
State& state, HashMap& hash_table, F&& creator,
530-
FF&& creator_for_null_key,
531-
PreHandler&& pre_handler) {
528+
void process_submap_emplace_void(Submap& submap, const uint32_t* indices, size_t count,
529+
HashMethodType& agg_method, State& state, HashMap& hash_table,
530+
F&& creator, FF&& creator_for_null_key, PreHandler&& pre_handler) {
532531
for (size_t j = 0; j < count; j++) {
533532
if constexpr (group_needs_prefetch<GroupIdx>) {
534533
if (j + HASH_MAP_PREFETCH_DIST < count) {
@@ -566,9 +565,9 @@ ALWAYS_INLINE void process_submap_emplace_void(Submap& submap, const uint32_t* i
566565
/// Process one sub-table group for find with result_handler.
567566
template <int GroupIdx, bool is_nullable, typename Submap, typename HashMethodType, typename State,
568567
typename HashMap, typename ResultHandler>
569-
ALWAYS_INLINE void process_submap_find(Submap& submap, const uint32_t* indices, size_t count,
570-
HashMethodType& agg_method, State& state,
571-
HashMap& hash_table, ResultHandler&& result_handler) {
568+
void process_submap_find(Submap& submap, const uint32_t* indices, size_t count,
569+
HashMethodType& agg_method, State& state, HashMap& hash_table,
570+
ResultHandler&& result_handler) {
572571
using Mapped = typename HashMethodType::Mapped;
573572
using FindResult = typename ColumnsHashing::columns_hashing_impl::FindResultImpl<Mapped>;
574573
for (size_t j = 0; j < count; j++) {
@@ -606,10 +605,14 @@ ALWAYS_INLINE void process_submap_find(Submap& submap, const uint32_t* indices,
606605

607606
/// Batch emplace helper: for StringHashMap, directly accesses sub-tables bypassing dispatch();
608607
/// for other hash maps, does per-row loop with standard prefetch.
609-
/// The result_handler is called for each row: result_handler(row_index, emplace_result)
610-
template <typename HashMethodType, typename State, typename F, typename FF, typename ResultHandler>
608+
/// pre_handler(row) is called before each emplace, allowing callers to set per-row state
609+
/// (e.g., current row index used inside creator lambdas).
610+
/// result_handler(row_index, mapped) is called after each emplace.
611+
template <typename HashMethodType, typename State, typename F, typename FF, typename PreHandler,
612+
typename ResultHandler>
611613
void lazy_emplace_batch(HashMethodType& agg_method, State& state, uint32_t num_rows, F&& creator,
612-
FF&& creator_for_null_key, ResultHandler&& result_handler) {
614+
FF&& creator_for_null_key, PreHandler&& pre_handler,
615+
ResultHandler&& result_handler) {
613616
if constexpr (HashMethodType::is_string_hash_map()) {
614617
using HashMap = typename HashMethodType::HashMapType;
615618
constexpr bool is_nullable = IsNullableStringHashMap<HashMap>::value;
@@ -622,22 +625,33 @@ void lazy_emplace_batch(HashMethodType& agg_method, State& state, uint32_t num_r
622625
constexpr int G = decltype(group_idx)::value;
623626
const auto& indices = groups.group_row_indices[G];
624627
if (!indices.empty()) {
625-
process_submap_emplace<G, is_nullable>(submap, indices.data(), indices.size(),
626-
agg_method, state, hash_table, creator,
627-
creator_for_null_key, result_handler);
628+
process_submap_emplace<G, is_nullable>(
629+
submap, indices.data(), indices.size(), agg_method, state, hash_table,
630+
creator, creator_for_null_key, pre_handler, result_handler);
628631
}
629632
});
630633
} else {
631634
// Standard per-row loop with ahead prefetch
632635
for (uint32_t i = 0; i < num_rows; ++i) {
633636
agg_method.template prefetch<false>(i);
637+
pre_handler(i);
634638
result_handler(i, *state.lazy_emplace_key(*agg_method.hash_table, i, agg_method.keys[i],
635639
agg_method.hash_values[i], creator,
636640
creator_for_null_key));
637641
}
638642
}
639643
}
640644

645+
/// Convenience overload without pre_handler (uses no-op).
646+
template <typename HashMethodType, typename State, typename F, typename FF, typename ResultHandler>
647+
void lazy_emplace_batch(HashMethodType& agg_method, State& state, uint32_t num_rows, F&& creator,
648+
FF&& creator_for_null_key, ResultHandler&& result_handler) {
649+
lazy_emplace_batch(
650+
agg_method, state, num_rows, std::forward<F>(creator),
651+
std::forward<FF>(creator_for_null_key), [](uint32_t) {},
652+
std::forward<ResultHandler>(result_handler));
653+
}
654+
641655
/// Batch emplace helper (void version): like lazy_emplace_batch but ignores the return value.
642656
/// pre_handler(row) is called before each emplace, allowing callers to update captured state
643657
/// (e.g., the current row index used inside creator lambdas).

0 commit comments

Comments
 (0)