Add ChunkAllocator to accelerate chunk allocation (#1792)
I add ChunkAllocator in this CL to put unused memory chunk to a chunk pool other than return it to system allocator. Now we only change MemPool's chunk allocation and free to this. And two configuration are introduduced too. 'chunk_reserved_bytes_limit' is the limit of how many bytes this chunk pool can reserve in total and its default value is 2147483648(2GB). 'use_mmap_allocate_chunk': if chunk is allocated via mmap and default value is false. And in my test case with default configuration a simple like "select * from table limit 10", this can improve throughput from 280 QPS to to 650 QPS. And when I config 'chunk_reserved_bytes_limit' to 0, which means this is disabled, the throughput is the same with origin's.
This commit is contained in:
78
be/src/runtime/memory/system_allocator.cpp
Normal file
78
be/src/runtime/memory/system_allocator.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "runtime/memory/system_allocator.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
namespace doris {
|
||||
|
||||
#define PAGE_SIZE (4 * 1024) // 4K
|
||||
|
||||
uint8_t* SystemAllocator::allocate(size_t length) {
|
||||
if (config::use_mmap_allocate_chunk) {
|
||||
return allocate_via_mmap(length);
|
||||
} else {
|
||||
return allocate_via_malloc(length);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemAllocator::free(uint8_t* ptr, size_t length) {
|
||||
if (config::use_mmap_allocate_chunk) {
|
||||
auto res = munmap(ptr, length);
|
||||
if (res != 0) {
|
||||
char buf[64];
|
||||
LOG(ERROR) << "fail to free memory via munmap, errno=" << errno
|
||||
<< ", errmsg=" << strerror_r(errno, buf, 64);
|
||||
}
|
||||
} else {
|
||||
::free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* SystemAllocator::allocate_via_malloc(size_t length) {
|
||||
void* ptr = nullptr;
|
||||
// try to use a whole page instead of parts of one page
|
||||
int res = posix_memalign(&ptr, PAGE_SIZE, length);
|
||||
if (res != 0) {
|
||||
char buf[64];
|
||||
LOG(ERROR) << "fail to allocate mem via posix_memalign, res=" << res
|
||||
<< ", errmsg=" << strerror_r(res, buf, 64);
|
||||
return nullptr;
|
||||
}
|
||||
return (uint8_t*)ptr;
|
||||
}
|
||||
|
||||
uint8_t* SystemAllocator::allocate_via_mmap(size_t length) {
|
||||
auto ptr = (uint8_t*)mmap(nullptr, length, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
char buf[64];
|
||||
LOG(ERROR) << "fail to allocate memory via mmap, errno=" << errno
|
||||
<< ", errmsg=" << strerror_r(errno, buf, 64);
|
||||
return nullptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user