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

Method AllocateInternal

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

Source from the content-addressed store, hash-verified

272}
273
274Status BufferPool::BufferAllocator::AllocateInternal(
275 BufferPool::Client* client, int64_t len, BufferHandle* buffer) {
276 DCHECK(!buffer->is_open());
277 DCHECK_GE(len, min_buffer_len_);
278 DCHECK(BitUtil::IsPowerOf2(len)) << len;
279
280 if (UNLIKELY(len > MAX_BUFFER_BYTES)) {
281 return Status(Substitute(
282 "Tried to allocate buffer of $0 bytes > max of $1 bytes", len, MAX_BUFFER_BYTES));
283 }
284 if (UNLIKELY(len > system_bytes_limit_)) {
285 return Status(Substitute("Tried to allocate buffer of $0 bytes > buffer pool limit "
286 "of $1 bytes", len, system_bytes_limit_));
287 }
288
289 const int current_core = CpuInfo::GetCurrentCore();
290 // Fast path: recycle a buffer of the correct size from this core's arena.
291 FreeBufferArena* current_core_arena = per_core_arenas_[current_core].get();
292 if (current_core_arena->PopFreeBuffer(len, buffer)) {
293 current_core_arena->local_arena_free_buffer_hits()->Increment(1);
294 return Status::OK();
295 }
296
297 // Fast-ish path: allocate a new buffer if there is room in 'system_bytes_remaining_'.
298 int64_t delta = DecreaseBytesRemaining(len, true, &system_bytes_remaining_);
299 // Whether to record stats about the system alloc (we don't want to do this every
300 // allocation because of the overhead).
301 bool sample_sys_alloc_stats = false;
302 if (delta == len) {
303 int64_t count = current_core_arena->direct_alloc_count()->Increment(1);
304 sample_sys_alloc_stats = count % ALLOC_STAT_SAMPLE_RATE == 0;
305 } else {
306 DCHECK_EQ(0, delta);
307 const vector<int>& numa_node_cores = CpuInfo::GetCoresOfSameNumaNode(current_core);
308 const int numa_node_core_idx = CpuInfo::GetNumaNodeCoreIdx(current_core);
309
310 // Fast-ish path: find a buffer of the right size from another core on the same
311 // NUMA node. Avoid getting a buffer from another NUMA node - prefer reclaiming
312 // a clean page on this NUMA node or scavenging then reallocating a new buffer.
313 // We don't want to get into a state where allocations between the nodes are
314 // unbalanced and one node is stuck reusing memory allocated on the other node.
315 for (int i = 1; i < numa_node_cores.size(); ++i) {
316 // Each core should start searching from a different point to avoid hot-spots.
317 int other_core = numa_node_cores[(numa_node_core_idx + i) % numa_node_cores.size()];
318 FreeBufferArena* other_core_arena = per_core_arenas_[other_core].get();
319 if (other_core_arena->PopFreeBuffer(len, buffer)) {
320 current_core_arena->numa_arena_free_buffer_hits()->Increment(1);
321 return Status::OK();
322 }
323 }
324
325 // Fast-ish path: evict a clean page of the right size from the current NUMA node.
326 for (int i = 0; i < numa_node_cores.size(); ++i) {
327 int other_core = numa_node_cores[(numa_node_core_idx + i) % numa_node_cores.size()];
328 FreeBufferArena* other_core_arena = per_core_arenas_[other_core].get();
329 if (other_core_arena->EvictCleanPage(len, buffer)) {
330 current_core_arena->clean_page_hits()->Increment(1);
331 return Status::OK();

Callers

nothing calls this directly

Calls 15

SubstituteFunction · 0.85
OKFunction · 0.85
DecreaseBytesRemainingFunction · 0.85
direct_alloc_countMethod · 0.80
EvictCleanPageMethod · 0.80
clean_page_hitsMethod · 0.80
num_scavengesMethod · 0.80
num_final_scavengesMethod · 0.80
buffer_size_statsMethod · 0.80
system_alloc_timeMethod · 0.80

Tested by

no test coverage detected