| 232 | |
| 233 | template <bool needSort> |
| 234 | void SpillableWindowBuild<needSort>::ensureInputFits( |
| 235 | const RowVectorPtr& input) { |
| 236 | if (spillConfig_ == nullptr) { |
| 237 | // Spilling is disabled. |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | if (data_->numRows() == 0) { |
| 242 | // Nothing to spill. |
| 243 | return; |
| 244 | } |
| 245 | |
| 246 | // Test-only spill path. |
| 247 | if (spillConfig_->testSpillPct > 0 && inputRows_.size() > 0) { |
| 248 | spill(); |
| 249 | return; |
| 250 | } |
| 251 | |
| 252 | auto [freeRows, outOfLineFreeBytes] = data_->freeSpace(); |
| 253 | const auto outOfLineBytes = |
| 254 | data_->stringAllocator().retainedSize() - outOfLineFreeBytes; |
| 255 | const auto outOfLineBytesPerRow = outOfLineBytes / data_->numRows(); |
| 256 | |
| 257 | const auto currentUsage = data_->pool()->currentBytes(); |
| 258 | const auto minReservationBytes = |
| 259 | currentUsage * spillConfig_->minSpillableReservationPct / 100; |
| 260 | const auto availableReservationBytes = data_->pool()->availableReservation(); |
| 261 | const auto incrementBytes = |
| 262 | data_->sizeIncrement(input->size(), outOfLineBytesPerRow * input->size()); |
| 263 | |
| 264 | // First to check if we have sufficient minimal memory reservation. |
| 265 | if (availableReservationBytes >= minReservationBytes) { |
| 266 | if ((freeRows > input->size()) && |
| 267 | (outOfLineBytes == 0 || |
| 268 | outOfLineFreeBytes >= outOfLineBytesPerRow * input->size())) { |
| 269 | // Enough free rows for input rows and enough variable length free space. |
| 270 | return; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | // Check if we can increase reservation. The increment is the largest of twice |
| 275 | // the maximum increment from this input and 'spillableReservationGrowthPct_' |
| 276 | // of the current memory usage. |
| 277 | const auto targetIncrementBytes = std::max<int64_t>( |
| 278 | incrementBytes * 2, |
| 279 | currentUsage * spillConfig_->spillableReservationGrowthPct / 100); |
| 280 | { |
| 281 | memory::ReclaimableSectionGuard guard(nonReclaimableSection_); |
| 282 | if (data_->pool()->maybeReserve(targetIncrementBytes)) { |
| 283 | return; |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | LOG(WARNING) << "Failed to reserve " << succinctBytes(targetIncrementBytes) |
| 288 | << " for memory pool " << data_->pool()->name() |
| 289 | << ", usage: " << succinctBytes(data_->pool()->currentBytes()) |
| 290 | << ", reservation: " |
| 291 | << succinctBytes(data_->pool()->reservedBytes()); |
nothing calls this directly
no test coverage detected