a specialized higher-performance variation of Hashing64 logic from hash_join_node the code here avoids recreating objects that are independent of each batch processed
| 387 | // a specialized higher-performance variation of Hashing64 logic from hash_join_node |
| 388 | // the code here avoids recreating objects that are independent of each batch processed |
| 389 | class KeyHasher { |
| 390 | friend class AsofJoinNode; |
| 391 | |
| 392 | static constexpr int kMiniBatchLength = arrow::util::MiniBatch::kMiniBatchLength; |
| 393 | |
| 394 | public: |
| 395 | // the key hasher is not thread-safe and is only used in sequential batch processing |
| 396 | // of the input it is associated with |
| 397 | KeyHasher(size_t index, const std::vector<col_index_t>& indices) |
| 398 | : index_(index), |
| 399 | indices_(indices), |
| 400 | metadata_(indices.size()), |
| 401 | batch_(NULLPTR), |
| 402 | hashes_(), |
| 403 | ctx_(), |
| 404 | column_arrays_(), |
| 405 | stack_() { |
| 406 | ctx_.stack = &stack_; |
| 407 | column_arrays_.resize(indices.size()); |
| 408 | } |
| 409 | |
| 410 | Status Init(ExecContext* exec_context, const std::shared_ptr<arrow::Schema>& schema) { |
| 411 | ctx_.hardware_flags = exec_context->cpu_info()->hardware_flags(); |
| 412 | const auto& fields = schema->fields(); |
| 413 | for (size_t k = 0; k < metadata_.size(); k++) { |
| 414 | ARROW_ASSIGN_OR_RAISE(metadata_[k], |
| 415 | ColumnMetadataFromDataType(fields[indices_[k]]->type())); |
| 416 | } |
| 417 | return stack_.Init(exec_context->memory_pool(), |
| 418 | 4 * kMiniBatchLength * sizeof(uint32_t)); |
| 419 | } |
| 420 | |
| 421 | // invalidate cached hashes for batch - required when it changes |
| 422 | // only this method can be called concurrently with HashesFor |
| 423 | void Invalidate() { batch_ = NULLPTR; } |
| 424 | |
| 425 | // compute and cache a hash for each row of the given batch |
| 426 | const std::vector<HashType>& HashesFor(const RecordBatch* batch) { |
| 427 | if (batch_ == batch) { |
| 428 | return hashes_; // cache hit - return cached hashes |
| 429 | } |
| 430 | Invalidate(); |
| 431 | size_t batch_length = batch->num_rows(); |
| 432 | hashes_.resize(batch_length); |
| 433 | for (int64_t i = 0; i < static_cast<int64_t>(batch_length); i += kMiniBatchLength) { |
| 434 | int64_t length = std::min(static_cast<int64_t>(batch_length - i), |
| 435 | static_cast<int64_t>(kMiniBatchLength)); |
| 436 | for (size_t k = 0; k < indices_.size(); k++) { |
| 437 | auto array_data = batch->column_data(indices_[k]); |
| 438 | column_arrays_[k] = |
| 439 | ColumnArrayFromArrayDataAndMetadata(array_data, metadata_[k], i, length); |
| 440 | } |
| 441 | // write directly to the cache |
| 442 | Hashing64::HashMultiColumn(column_arrays_, &ctx_, hashes_.data() + i); |
| 443 | } |
| 444 | DEBUG_SYNC(node_, "key hasher ", index_, " got hashes ", |
| 445 | compute::internal::GenericToString(hashes_), DEBUG_MANIP(std::endl)); |
| 446 | batch_ = batch; // associate cache with current batch |
nothing calls this directly
no test coverage detected