| 753 | } |
| 754 | |
| 755 | bool HashBuild::reserveMemory( |
| 756 | const RowVectorPtr& input, |
| 757 | SpilledRows spilledRows) { |
| 758 | BOLT_CHECK(spillEnabled()); |
| 759 | |
| 760 | Operator::ReclaimableSectionGuard guard(this); |
| 761 | numSpillRows_ = 0; |
| 762 | numSpillBytes_ = 0; |
| 763 | |
| 764 | auto* rows = table_->rows(); |
| 765 | const auto numRows = rows->numRows(); |
| 766 | |
| 767 | auto [freeRows, outOfLineFreeBytes] = rows->freeSpace(); |
| 768 | const auto outOfLineBytes = |
| 769 | rows->stringAllocator().retainedSize() - outOfLineFreeBytes; |
| 770 | const auto outOfLineBytesPerRow = |
| 771 | std::max<uint64_t>(1, numRows == 0 ? 0 : outOfLineBytes / numRows); |
| 772 | const auto currentUsage = pool()->currentBytes(); |
| 773 | |
| 774 | if (numRows != 0) { |
| 775 | // Test-only spill path. |
| 776 | if (testingTriggerSpill()) { |
| 777 | numSpillRows_ = std::max<int64_t>(1, numRows / 10); |
| 778 | numSpillBytes_ = numSpillRows_ * outOfLineBytesPerRow; |
| 779 | return false; |
| 780 | } |
| 781 | |
| 782 | // We check usage from the parent pool to take peers' allocations into |
| 783 | // account. |
| 784 | auto nodeUsage = pool()->currentBytes(); |
| 785 | // For hybrid join without scattered mode, include payload memory that |
| 786 | // is not tracked by the pool but will be needed during coalesceBatches(). |
| 787 | if (hybridJoin_ && table_->hybridData() && !scatteredMode_) { |
| 788 | nodeUsage += table_->hybridData()->payloadMemoryBytes(); |
| 789 | } |
| 790 | if (spillMemoryThreshold_ != 0 && nodeUsage > spillMemoryThreshold_) { |
| 791 | const int64_t bytesToSpill = |
| 792 | nodeUsage * spillConfig()->spillableReservationGrowthPct / 100; |
| 793 | numSpillRows_ = std::max<int64_t>( |
| 794 | 1, bytesToSpill / (rows->fixedRowSize() + outOfLineBytesPerRow)); |
| 795 | numSpillBytes_ = numSpillRows_ * outOfLineBytesPerRow; |
| 796 | return false; |
| 797 | } |
| 798 | } |
| 799 | bool rowBasedSpill = spilledRows.rows != nullptr; |
| 800 | |
| 801 | auto inputBytes = |
| 802 | rowBasedSpill ? spilledRows.size : input->estimateFlatSize(); |
| 803 | auto inputNum = rowBasedSpill ? spilledRows.rows->size() : input->size(); |
| 804 | |
| 805 | const auto minReservationBytes = |
| 806 | currentUsage * spillConfig_->minSpillableReservationPct / 100; |
| 807 | const auto availableReservationBytes = pool()->availableReservation(); |
| 808 | const auto tableIncrementBytes = table_->hashTableSizeIncrease(inputNum); |
| 809 | const int64_t flatBytes = inputBytes; |
| 810 | const auto rowContainerIncrementBytes = numRows == 0 |
| 811 | ? flatBytes * 2 |
| 812 | : rows->sizeIncrement(inputNum, outOfLineBytes > 0 ? flatBytes * 2 : 0); |
nothing calls this directly
no test coverage detected