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:
ZHAO Chun
2019-09-13 08:27:24 +08:00
committed by GitHub
parent 9aa2045987
commit 11eafe524f
17 changed files with 583 additions and 46 deletions

View 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;
}
}