This is an automated email from the ASF dual-hosted git repository.

zanmato pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new ea0b3c5226 GH-45877: [C++][Acero] Cleanup 64-bit temp states of Swiss 
join by using 32-bit (#45878)
ea0b3c5226 is described below

commit ea0b3c522693b4afea82f492dc10f894fabbee58
Author: Rossi Sun <[email protected]>
AuthorDate: Mon Mar 24 13:16:47 2025 +0800

    GH-45877: [C++][Acero] Cleanup 64-bit temp states of Swiss join by using 
32-bit (#45878)
    
    ### Rationale for this change
    
    See #45877.
    
    ### What changes are included in this PR?
    
    1. Normalize all temp states/variables representing "row id"s to `uint32_t`.
    2. Cleanup many `DCHECK`s (some added though) and `static_cast`s.
    
    ### Are these changes tested?
    
    Existing tests should suffice.
    
    ### Are there any user-facing changes?
    
    None.
    
    * GitHub Issue: #45877
    
    Authored-by: Rossi Sun <[email protected]>
    Signed-off-by: Rossi Sun <[email protected]>
---
 cpp/src/arrow/acero/swiss_join.cc         | 113 ++++++++++++++++--------------
 cpp/src/arrow/acero/swiss_join_internal.h |  22 +++---
 2 files changed, 70 insertions(+), 65 deletions(-)

diff --git a/cpp/src/arrow/acero/swiss_join.cc 
b/cpp/src/arrow/acero/swiss_join.cc
index b4d89df290..a32ea7d3ac 100644
--- a/cpp/src/arrow/acero/swiss_join.cc
+++ b/cpp/src/arrow/acero/swiss_join.cc
@@ -392,7 +392,7 @@ void RowArray::DecodeNulls(ResizableArrayData* output, int 
output_start_row,
 
 Status RowArrayMerge::PrepareForMerge(RowArray* target,
                                       const std::vector<RowArray*>& sources,
-                                      std::vector<int64_t>* 
first_target_row_id,
+                                      std::vector<uint32_t>* 
first_target_row_id,
                                       MemoryPool* pool, int64_t 
hardware_flags) {
   ARROW_DCHECK(!sources.empty());
 
@@ -404,7 +404,7 @@ Status RowArrayMerge::PrepareForMerge(RowArray* target,
   // Sum the number of rows from all input sources and calculate their total
   // size.
   //
-  int64_t num_rows = 0;
+  uint32_t num_rows = 0;
   int64_t num_bytes = 0;
   if (first_target_row_id) {
     first_target_row_id->resize(sources.size() + 1);
@@ -417,7 +417,9 @@ Status RowArrayMerge::PrepareForMerge(RowArray* target,
     if (first_target_row_id) {
       (*first_target_row_id)[i] = num_rows;
     }
-    num_rows += sources[i]->rows_.length();
+    DCHECK_LE(num_rows + sources[i]->rows_.length(),
+              std::numeric_limits<uint32_t>::max());
+    num_rows += static_cast<uint32_t>(sources[i]->rows_.length());
     if (!metadata.is_fixed_length) {
       num_bytes += sources[i]->rows_.offsets()[sources[i]->rows_.length()];
     }
@@ -429,7 +431,7 @@ Status RowArrayMerge::PrepareForMerge(RowArray* target,
   // Allocate target memory
   //
   target->rows_.Clean();
-  RETURN_NOT_OK(target->rows_.AppendEmpty(static_cast<uint32_t>(num_rows), 
num_bytes));
+  RETURN_NOT_OK(target->rows_.AppendEmpty(num_rows, num_bytes));
 
   // In case of varying length rows,
   // initialize the first row offset for each range of rows corresponding to a
@@ -440,7 +442,9 @@ Status RowArrayMerge::PrepareForMerge(RowArray* target,
     num_bytes = 0;
     for (size_t i = 0; i < sources.size(); ++i) {
       target->rows_.mutable_offsets()[num_rows] = num_bytes;
-      num_rows += sources[i]->rows_.length();
+      DCHECK_LE(num_rows + sources[i]->rows_.length(),
+                std::numeric_limits<uint32_t>::max());
+      num_rows += static_cast<uint32_t>(sources[i]->rows_.length());
       num_bytes += sources[i]->rows_.offsets()[sources[i]->rows_.length()];
     }
     target->rows_.mutable_offsets()[num_rows] = num_bytes;
@@ -450,8 +454,8 @@ Status RowArrayMerge::PrepareForMerge(RowArray* target,
 }
 
 void RowArrayMerge::MergeSingle(RowArray* target, const RowArray& source,
-                                int64_t first_target_row_id,
-                                const int64_t* source_rows_permutation) {
+                                uint32_t first_target_row_id,
+                                const uint32_t* source_rows_permutation) {
   // Source and target must:
   // - be initialized
   // - use the same row format
@@ -473,8 +477,8 @@ void RowArrayMerge::MergeSingle(RowArray* target, const 
RowArray& source,
 }
 
 void RowArrayMerge::CopyFixedLength(RowTableImpl* target, const RowTableImpl& 
source,
-                                    int64_t first_target_row_id,
-                                    const int64_t* source_rows_permutation) {
+                                    uint32_t first_target_row_id,
+                                    const uint32_t* source_rows_permutation) {
   int64_t num_source_rows = source.length();
 
   uint32_t fixed_length = target->metadata().fixed_length;
@@ -483,8 +487,7 @@ void RowArrayMerge::CopyFixedLength(RowTableImpl* target, 
const RowTableImpl& so
   // needed is memcpy.
   //
   if (!source_rows_permutation) {
-    DCHECK_LE(first_target_row_id, std::numeric_limits<uint32_t>::max());
-    
memcpy(target->mutable_fixed_length_rows(static_cast<uint32_t>(first_target_row_id)),
+    memcpy(target->mutable_fixed_length_rows(first_target_row_id),
            source.fixed_length_rows(/*row_id=*/0), fixed_length * 
num_source_rows);
   } else {
     // Row length must be a multiple of 64-bits due to enforced alignment.
@@ -493,15 +496,13 @@ void RowArrayMerge::CopyFixedLength(RowTableImpl* target, 
const RowTableImpl& so
     ARROW_DCHECK(fixed_length % sizeof(uint64_t) == 0);
 
     int64_t num_words_per_row = fixed_length / sizeof(uint64_t);
-    for (int64_t i = 0; i < num_source_rows; ++i) {
-      int64_t source_row_id = source_rows_permutation[i];
-      DCHECK_LE(source_row_id, std::numeric_limits<uint32_t>::max());
-      const uint64_t* source_row_ptr = reinterpret_cast<const uint64_t*>(
-          source.fixed_length_rows(static_cast<uint32_t>(source_row_id)));
-      int64_t target_row_id = first_target_row_id + i;
-      DCHECK_LE(target_row_id, std::numeric_limits<uint32_t>::max());
-      uint64_t* target_row_ptr = reinterpret_cast<uint64_t*>(
-          
target->mutable_fixed_length_rows(static_cast<uint32_t>(target_row_id)));
+    for (uint32_t i = 0; i < num_source_rows; ++i) {
+      uint32_t source_row_id = source_rows_permutation[i];
+      const uint64_t* source_row_ptr =
+          reinterpret_cast<const 
uint64_t*>(source.fixed_length_rows(source_row_id));
+      uint32_t target_row_id = first_target_row_id + i;
+      uint64_t* target_row_ptr =
+          
reinterpret_cast<uint64_t*>(target->mutable_fixed_length_rows(target_row_id));
 
       for (int64_t word = 0; word < num_words_per_row; ++word) {
         target_row_ptr[word] = source_row_ptr[word];
@@ -511,9 +512,9 @@ void RowArrayMerge::CopyFixedLength(RowTableImpl* target, 
const RowTableImpl& so
 }
 
 void RowArrayMerge::CopyVaryingLength(RowTableImpl* target, const 
RowTableImpl& source,
-                                      int64_t first_target_row_id,
+                                      uint32_t first_target_row_id,
                                       int64_t first_target_row_offset,
-                                      const int64_t* source_rows_permutation) {
+                                      const uint32_t* source_rows_permutation) 
{
   int64_t num_source_rows = source.length();
   RowTableImpl::offset_type* target_offsets = target->mutable_offsets();
   const RowTableImpl::offset_type* source_offsets = source.offsets();
@@ -540,7 +541,7 @@ void RowArrayMerge::CopyVaryingLength(RowTableImpl* target, 
const RowTableImpl&
     uint64_t* target_row_ptr = reinterpret_cast<uint64_t*>(
         target->mutable_var_length_rows() + target_row_offset);
     for (int64_t i = 0; i < num_source_rows; ++i) {
-      int64_t source_row_id = source_rows_permutation[i];
+      uint32_t source_row_id = source_rows_permutation[i];
       const uint64_t* source_row_ptr = reinterpret_cast<const uint64_t*>(
           source.var_length_rows() + source_offsets[source_row_id]);
       int64_t length = source_offsets[source_row_id + 1] - 
source_offsets[source_row_id];
@@ -564,22 +565,18 @@ void RowArrayMerge::CopyVaryingLength(RowTableImpl* 
target, const RowTableImpl&
 }
 
 void RowArrayMerge::CopyNulls(RowTableImpl* target, const RowTableImpl& source,
-                              int64_t first_target_row_id,
-                              const int64_t* source_rows_permutation) {
+                              uint32_t first_target_row_id,
+                              const uint32_t* source_rows_permutation) {
   int64_t num_source_rows = source.length();
   int num_bytes_per_row = target->metadata().null_masks_bytes_per_row;
-  DCHECK_LE(first_target_row_id, std::numeric_limits<uint32_t>::max());
-  uint8_t* target_nulls =
-      target->mutable_null_masks(static_cast<uint32_t>(first_target_row_id));
+  uint8_t* target_nulls = target->mutable_null_masks(first_target_row_id);
   if (!source_rows_permutation) {
     memcpy(target_nulls, source.null_masks(/*row_id=*/0),
            num_bytes_per_row * num_source_rows);
   } else {
     for (uint32_t i = 0; i < num_source_rows; ++i) {
-      int64_t source_row_id = source_rows_permutation[i];
-      DCHECK_LE(source_row_id, std::numeric_limits<uint32_t>::max());
-      const uint8_t* source_nulls =
-          source.null_masks(static_cast<uint32_t>(source_row_id));
+      uint32_t source_row_id = source_rows_permutation[i];
+      const uint8_t* source_nulls = source.null_masks(source_row_id);
       for (int64_t byte = 0; byte < num_bytes_per_row; ++byte) {
         *target_nulls++ = *source_nulls++;
       }
@@ -1301,10 +1298,12 @@ Status SwissTableForJoinBuild::PreparePrtnMerge() {
 
   // Check if we have duplicate keys
   //
-  int64_t num_keys = partition_keys_first_row_id_[num_prtns_];
-  int64_t num_rows = 0;
+  uint32_t num_keys = partition_keys_first_row_id_[num_prtns_];
+  uint32_t num_rows = 0;
   for (int i = 0; i < num_prtns_; ++i) {
-    num_rows += static_cast<int64_t>(prtn_states_[i].key_ids.size());
+    DCHECK_LE(num_rows + prtn_states_[i].key_ids.size(),
+              std::numeric_limits<uint32_t>::max());
+    num_rows += static_cast<uint32_t>(prtn_states_[i].key_ids.size());
   }
   bool no_duplicate_keys = reject_duplicate_keys_ || num_keys == num_rows;
 
@@ -1313,13 +1312,15 @@ Status SwissTableForJoinBuild::PreparePrtnMerge() {
   target_->no_duplicate_keys_ = no_duplicate_keys;
   if (!no_duplicate_keys) {
     target_->row_offset_for_key_.resize(num_keys + 1);
-    int64_t num_rows = 0;
+    uint32_t num_rows = 0;
     for (int i = 0; i < num_prtns_; ++i) {
-      int64_t first_key = partition_keys_first_row_id_[i];
-      target_->row_offset_for_key_[first_key] = 
static_cast<uint32_t>(num_rows);
-      num_rows += static_cast<int64_t>(prtn_states_[i].key_ids.size());
+      uint32_t first_key = partition_keys_first_row_id_[i];
+      target_->row_offset_for_key_[first_key] = num_rows;
+      DCHECK_LE(num_rows + prtn_states_[i].key_ids.size(),
+                std::numeric_limits<uint32_t>::max());
+      num_rows += static_cast<uint32_t>(prtn_states_[i].key_ids.size());
     }
-    target_->row_offset_for_key_[num_keys] = static_cast<uint32_t>(num_rows);
+    target_->row_offset_for_key_[num_keys] = num_rows;
   }
 
   return Status::OK();
@@ -1327,6 +1328,10 @@ Status SwissTableForJoinBuild::PreparePrtnMerge() {
 
 void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
   PartitionState& prtn_state = prtn_states_[prtn_id];
+  // Emscripten has size_t as unsigned long thus warns about this comparison 
being always
+  // true. We explicit cast to unsigned long long.
+  DCHECK_LE(static_cast<uint64_t>(prtn_state.key_ids.size()),
+            std::numeric_limits<uint32_t>::max() + 1ull);
 
   // There are 4 data structures that require partition merging:
   // 1. array of key rows
@@ -1346,10 +1351,10 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
   //
   SwissTableMerge::MergePartition(
       target_->map_.swiss_table(), prtn_state.keys.swiss_table(), prtn_id, 
log_num_prtns_,
-      static_cast<uint32_t>(partition_keys_first_row_id_[prtn_id]),
-      &prtn_state.overflow_key_ids, &prtn_state.overflow_hashes);
+      partition_keys_first_row_id_[prtn_id], &prtn_state.overflow_key_ids,
+      &prtn_state.overflow_hashes);
 
-  std::vector<int64_t> source_payload_ids;
+  std::vector<uint32_t> source_payload_ids;
 
   // 3. mapping from key id to first payload id
   //
@@ -1360,11 +1365,11 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
     // For convenience, we use an array in merged hash table mapping key ids to
     // first payload ids to collect the counters.
     //
-    int64_t first_key = partition_keys_first_row_id_[prtn_id];
-    int64_t num_keys = partition_keys_first_row_id_[prtn_id + 1] - first_key;
+    uint32_t first_key = partition_keys_first_row_id_[prtn_id];
+    uint32_t num_keys = partition_keys_first_row_id_[prtn_id + 1] - first_key;
     uint32_t* counters = target_->row_offset_for_key_.data() + first_key;
     uint32_t first_payload = counters[0];
-    for (int64_t i = 0; i < num_keys; ++i) {
+    for (uint32_t i = 0; i < num_keys; ++i) {
       counters[i] = 0;
     }
     for (size_t i = 0; i < prtn_state.key_ids.size(); ++i) {
@@ -1378,7 +1383,7 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
       // Start by computing inclusive cumulative sum of counters.
       //
       uint32_t sum = 0;
-      for (int64_t i = 0; i < num_keys; ++i) {
+      for (uint32_t i = 0; i < num_keys; ++i) {
         sum += counters[i];
         counters[i] = sum;
       }
@@ -1388,14 +1393,14 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
       // there at the beginning).
       //
       source_payload_ids.resize(prtn_state.key_ids.size());
-      for (size_t i = 0; i < prtn_state.key_ids.size(); ++i) {
+      for (uint32_t i = 0; i < prtn_state.key_ids.size(); ++i) {
         uint32_t key_id = prtn_state.key_ids[i];
-        int64_t position = --counters[key_id];
-        source_payload_ids[position] = static_cast<int64_t>(i);
+        uint32_t position = --counters[key_id];
+        source_payload_ids[position] = i;
       }
       // Add base payload id to all of the counters.
       //
-      for (int64_t i = 0; i < num_keys; ++i) {
+      for (uint32_t i = 0; i < num_keys; ++i) {
         counters[i] += first_payload;
       }
     } else {
@@ -1403,7 +1408,7 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
       // cumulative sum of counters and add the base payload id to all of them.
       //
       uint32_t sum = 0;
-      for (int64_t i = 0; i < num_keys; ++i) {
+      for (uint32_t i = 0; i < num_keys; ++i) {
         uint32_t sum_next = sum + counters[i];
         counters[i] = sum + first_payload;
         sum = sum_next;
@@ -1419,9 +1424,9 @@ void SwissTableForJoinBuild::PrtnMerge(int prtn_id) {
     //
     if (target_->no_duplicate_keys_) {
       source_payload_ids.resize(prtn_state.key_ids.size());
-      for (size_t i = 0; i < prtn_state.key_ids.size(); ++i) {
+      for (uint32_t i = 0; i < prtn_state.key_ids.size(); ++i) {
         uint32_t key_id = prtn_state.key_ids[i];
-        source_payload_ids[key_id] = static_cast<int64_t>(i);
+        source_payload_ids[key_id] = i;
       }
     }
     // Merge partition payloads into target array using the permutation.
diff --git a/cpp/src/arrow/acero/swiss_join_internal.h 
b/cpp/src/arrow/acero/swiss_join_internal.h
index 365f2917d8..ab7c5acaa9 100644
--- a/cpp/src/arrow/acero/swiss_join_internal.h
+++ b/cpp/src/arrow/acero/swiss_join_internal.h
@@ -261,7 +261,7 @@ class RowArrayMerge {
   // caller can pass in nullptr to indicate that it is not needed.
   //
   static Status PrepareForMerge(RowArray* target, const 
std::vector<RowArray*>& sources,
-                                std::vector<int64_t>* first_target_row_id,
+                                std::vector<uint32_t>* first_target_row_id,
                                 MemoryPool* pool, int64_t hardware_flags);
 
   // Copy rows from source array to target array.
@@ -286,8 +286,8 @@ class RowArrayMerge {
   // initializes boundary offsets for target row ranges for each source).
   //
   static void MergeSingle(RowArray* target, const RowArray& source,
-                          int64_t first_target_row_id,
-                          const int64_t* source_rows_permutation);
+                          uint32_t first_target_row_id,
+                          const uint32_t* source_rows_permutation);
 
  private:
   // Copy rows from source array to a region of the target array.
@@ -295,24 +295,24 @@ class RowArrayMerge {
   // Null information needs to be handled separately.
   //
   static void CopyFixedLength(RowTableImpl* target, const RowTableImpl& source,
-                              int64_t first_target_row_id,
-                              const int64_t* source_rows_permutation);
+                              uint32_t first_target_row_id,
+                              const uint32_t* source_rows_permutation);
 
   // Copy rows from source array to a region of the target array.
   // This implementation is for varying length rows.
   // Null information needs to be handled separately.
   //
   static void CopyVaryingLength(RowTableImpl* target, const RowTableImpl& 
source,
-                                int64_t first_target_row_id,
+                                uint32_t first_target_row_id,
                                 int64_t first_target_row_offset,
-                                const int64_t* source_rows_permutation);
+                                const uint32_t* source_rows_permutation);
 
   // Copy null information from rows from source array to a region of the 
target
   // array.
   //
   static void CopyNulls(RowTableImpl* target, const RowTableImpl& source,
-                        int64_t first_target_row_id,
-                        const int64_t* source_rows_permutation);
+                        uint32_t first_target_row_id,
+                        const uint32_t* source_rows_permutation);
 };
 
 // Implements merging of multiple SwissTables into a single one, using
@@ -649,8 +649,8 @@ class SwissTableForJoinBuild {
   std::vector<PartitionState> prtn_states_;
   std::vector<ThreadState> thread_states_;
 
-  std::vector<int64_t> partition_keys_first_row_id_;
-  std::vector<int64_t> partition_payloads_first_row_id_;
+  std::vector<uint32_t> partition_keys_first_row_id_;
+  std::vector<uint32_t> partition_payloads_first_row_id_;
 };
 
 class JoinResultMaterialize {

Reply via email to