| 142 | } |
| 143 | |
| 144 | void SortWindowBuild::ensureInputFits(const RowVectorPtr& input) { |
| 145 | if (spillConfig_ == nullptr) { |
| 146 | // Spilling is disabled. |
| 147 | return; |
| 148 | } |
| 149 | |
| 150 | if (data_->numRows() == 0) { |
| 151 | // Nothing to spill. |
| 152 | return; |
| 153 | } |
| 154 | |
| 155 | // Test-only spill path. |
| 156 | if (testingTriggerSpill()) { |
| 157 | spill(); |
| 158 | return; |
| 159 | } |
| 160 | |
| 161 | auto [freeRows, outOfLineFreeBytes] = data_->freeSpace(); |
| 162 | const auto outOfLineBytes = |
| 163 | data_->stringAllocator().retainedSize() - outOfLineFreeBytes; |
| 164 | const auto outOfLineBytesPerRow = outOfLineBytes / data_->numRows(); |
| 165 | |
| 166 | const auto currentUsage = data_->pool()->currentBytes(); |
| 167 | const auto minReservationBytes = |
| 168 | currentUsage * spillConfig_->minSpillableReservationPct / 100; |
| 169 | const auto availableReservationBytes = data_->pool()->availableReservation(); |
| 170 | uint64_t tableIncrementBytes = 0; |
| 171 | if (table_) { |
| 172 | tableIncrementBytes = table_->hashTableSizeIncrease(input->size()); |
| 173 | } |
| 174 | const auto incrementBytes = |
| 175 | data_->sizeIncrement( |
| 176 | input->size(), outOfLineBytesPerRow * input->size()) + |
| 177 | tableIncrementBytes; |
| 178 | |
| 179 | // First to check if we have sufficient minimal memory reservation. |
| 180 | if (availableReservationBytes >= minReservationBytes) { |
| 181 | if ((tableIncrementBytes == 0) && (freeRows > input->size()) && |
| 182 | (outOfLineBytes == 0 || |
| 183 | outOfLineFreeBytes >= outOfLineBytesPerRow * input->size())) { |
| 184 | // Enough free rows for input rows and enough variable length free space. |
| 185 | return; |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | // Check if we can increase reservation. The increment is the largest of twice |
| 190 | // the maximum increment from this input and 'spillableReservationGrowthPct_' |
| 191 | // of the current memory usage. |
| 192 | const auto targetIncrementBytes = std::max<int64_t>( |
| 193 | incrementBytes * 2, |
| 194 | currentUsage * spillConfig_->spillableReservationGrowthPct / 100); |
| 195 | { |
| 196 | memory::ReclaimableSectionGuard guard(nonReclaimableSection_); |
| 197 | if (data_->pool()->maybeReserve(targetIncrementBytes)) { |
| 198 | return; |
| 199 | } |
| 200 | } |
| 201 |
nothing calls this directly
no test coverage detected