MCPcopy Create free account
hub / github.com/apache/impala / ScavengeBuffers

Method ScavengeBuffers

be/src/runtime/bufferpool/buffer-allocator.cc:386–435  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

384}
385
386int64_t BufferPool::BufferAllocator::ScavengeBuffers(
387 bool slow_but_sure, int current_core, int64_t target_bytes) {
388 // There are two strategies for scavenging buffers:
389 // 1) Fast, opportunistic: Each arena is searched in succession. Although reservations
390 // guarantee that the memory we need is available somewhere, this may fail if we
391 // we race with another thread that returned buffers to an arena that we've already
392 // searched and took the buffers from an arena we haven't yet searched.
393 // 2) Slow, guaranteed to succeed: In order to ensure that we can find the memory in a
394 // single pass, we hold locks for all arenas we've already examined. That way, other
395 // threads can't take the memory that we need from an arena that we haven't yet
396 // examined (or from 'system_bytes_available_') because in order to do so, it would
397 // have had to return the equivalent amount of memory to an earlier arena or added
398 // it back into 'systems_bytes_reamining_'. The former can't happen since we're
399 // still holding those locks, and the latter is solved by trying to decrease
400 // system_bytes_remaining_ with DecreaseBytesRemaining() at the end.
401 DCHECK_GT(target_bytes, 0);
402 // First make sure we've used up all the headroom in the buffer limit.
403 int64_t bytes_found =
404 DecreaseBytesRemaining(target_bytes, false, &system_bytes_remaining_);
405 if (bytes_found == target_bytes) return bytes_found;
406
407 // In 'slow_but_sure' mode, we will hold locks for multiple arenas at the same time and
408 // therefore must start at 0 to respect the lock order. Otherwise we start with the
409 // current core's arena for locality and to avoid excessive contention on arena 0.
410 int start_core = slow_but_sure ? 0 : current_core;
411 vector<std::unique_lock<SpinLock>> arena_locks;
412 if (slow_but_sure) arena_locks.resize(per_core_arenas_.size());
413
414 for (int i = 0; i < per_core_arenas_.size(); ++i) {
415 int core_to_check = (start_core + i) % per_core_arenas_.size();
416 FreeBufferArena* arena = per_core_arenas_[core_to_check].get();
417 int64_t bytes_needed = target_bytes - bytes_found;
418 bytes_found += arena->FreeSystemMemory(bytes_needed, bytes_needed,
419 slow_but_sure ? &arena_locks[i] : nullptr).second;
420 if (bytes_found == target_bytes) break;
421 }
422 DCHECK_LE(bytes_found, target_bytes);
423
424 // Decrement 'system_bytes_remaining_' while still holding the arena locks to avoid
425 // the window for a race with another thread that removes a buffer from a list and
426 // then increments 'system_bytes_remaining_'. The race is prevented because the other
427 // thread holds the lock while decrementing 'system_bytes_remaining_' in the cases
428 // where it may not have reservation corresponding to that memory.
429 if (slow_but_sure && bytes_found < target_bytes) {
430 bytes_found += DecreaseBytesRemaining(
431 target_bytes - bytes_found, true, &system_bytes_remaining_);
432 DCHECK_EQ(bytes_found, target_bytes) << DebugString();
433 }
434 return bytes_found;
435}
436
437void BufferPool::BufferAllocator::Free(BufferHandle&& handle) {
438 DCHECK(handle.is_open());

Callers

nothing calls this directly

Calls 6

DecreaseBytesRemainingFunction · 0.85
resizeMethod · 0.80
FreeSystemMemoryMethod · 0.80
getMethod · 0.65
DebugStringFunction · 0.50
sizeMethod · 0.45

Tested by

no test coverage detected