github-actions[bot] commented on code in PR #37234:
URL: https://github.com/apache/doris/pull/37234#discussion_r1689004788
##########
be/src/vec/common/allocator.cpp:
##########
@@ -40,8 +40,12 @@
#include "util/stack_util.h"
#include "util/uid_util.h"
-template <bool clear_memory_, bool mmap_populate, bool use_mmap>
-void Allocator<clear_memory_, mmap_populate,
use_mmap>::sys_memory_check(size_t size) const {
+std::unordered_map<void*, size_t> RecordSizeMemoryAllocator::_allocated_sizes;
+std::mutex RecordSizeMemoryAllocator::_mutex;
+
+template <bool clear_memory_, bool mmap_populate, bool use_mmap, typename
MemoryAllocator>
+void Allocator<clear_memory_, mmap_populate, use_mmap,
MemoryAllocator>::sys_memory_check(
Review Comment:
warning: function 'sys_memory_check' exceeds recommended size/complexity
thresholds [readability-function-size]
```cpp
void Allocator<clear_memory_, mmap_populate, use_mmap,
MemoryAllocator>::sys_memory_check(
^
```
<details>
<summary>Additional context</summary>
**be/src/vec/common/allocator.cpp:46:** 112 lines including whitespace and
comments (threshold 80)
```cpp
void Allocator<clear_memory_, mmap_populate, use_mmap,
MemoryAllocator>::sys_memory_check(
^
```
</details>
##########
be/src/vec/common/allocator.h:
##########
@@ -117,187 +237,205 @@
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot mmap {}.",
size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
/// No need for zero-fill, because mmap guarantees it.
} else {
if (alignment <= MALLOC_MIN_ALIGNMENT) {
if constexpr (clear_memory)
- buf = ::calloc(size, 1);
+ buf = MemoryAllocator::calloc(size, 1);
else
- buf = ::malloc(size);
+ buf = MemoryAllocator::malloc(size);
if (nullptr == buf) {
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot malloc
{}.", size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
} else {
buf = nullptr;
- int res = posix_memalign(&buf, alignment, size);
+ int res = MemoryAllocator::posix_memalign(&buf, alignment,
size);
if (0 != res) {
release_memory(size);
throw_bad_alloc(
fmt::format("Cannot allocate memory
(posix_memalign) {}.", size));
}
+
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
-
- if constexpr (clear_memory) memset(buf, 0, size);
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ consume_memory(record_size - size);
+ }
+ return buf;
}
- return buf;
- }
- /// Free memory range.
- void free(void* buf, size_t size) {
- if (use_mmap && size >= doris::config::mmap_threshold) {
- if (0 != munmap(buf, size)) {
- throw_bad_alloc(fmt::format("Allocator: Cannot munmap {}.",
size));
- }
- } else {
+ /// Free memory range.
+ void free(void* buf, size_t size) {
+ if (use_mmap && size >= doris::config::mmap_threshold) {
+ if (0 != munmap(buf, size)) {
+ throw_bad_alloc(fmt::format("Allocator: Cannot munmap
{}.", size));
+ }
+ } else {
#ifndef NDEBUG
- remove_address_sanitizers(buf, size);
+ remove_address_sanitizers(buf, size);
#endif
- ::free(buf);
+ MemoryAllocator::free(buf);
+ }
+ release_memory(size);
+ }
+
+ void release_unused() {
+ MemoryAllocator::release_unused();
}
- release_memory(size);
- }
- /** Enlarge memory range.
+ /** Enlarge memory range.
* Data from old range is moved to the beginning of new range.
* Address of memory range could change.
*/
- void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
- if (old_size == new_size) {
- /// nothing to do.
- /// BTW, it's not possible to change alignment while doing realloc.
- return buf;
- }
- memory_check(new_size);
- consume_memory(new_size - old_size);
+ void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
+ if (old_size == new_size) {
+ /// nothing to do.
+ /// BTW, it's not possible to change alignment while doing
realloc.
+ return buf;
+ }
+ memory_check(new_size);
+ consume_memory(new_size - old_size);
- if (!use_mmap ||
- (old_size < doris::config::mmap_threshold && new_size <
doris::config::mmap_threshold &&
- alignment <= MALLOC_MIN_ALIGNMENT)) {
+ if (!use_mmap ||
+ (old_size < doris::config::mmap_threshold &&
+ new_size < doris::config::mmap_threshold && alignment <=
MALLOC_MIN_ALIGNMENT)) {
#ifndef NDEBUG
- remove_address_sanitizers(buf, old_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- /// Resize malloc'd memory region with no special alignment
requirement.
- void* new_buf = ::realloc(buf, new_size);
- if (nullptr == new_buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot realloc from {}
to {}.", old_size,
- new_size));
- }
+ /// Resize malloc'd memory region with no special alignment
requirement.
+ void* new_buf = MemoryAllocator::realloc(buf, new_size);
+ if (nullptr == new_buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(fmt::format("Allocator: Cannot realloc
from {} to {}.",
+ old_size, new_size));
+ }
#ifndef NDEBUG
- add_address_sanitizers(
- new_buf, new_size); // usually, buf addr = new_buf addr,
asan maybe not equal.
+ add_address_sanitizers(
+ new_buf,
+ new_size); // usually, buf addr = new_buf addr, asan
maybe not equal.
#endif
- buf = new_buf;
- if constexpr (clear_memory)
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- } else if (old_size >= doris::config::mmap_threshold &&
- new_size >= doris::config::mmap_threshold) {
- /// Resize mmap'd memory region.
- // On apple and freebsd self-implemented mremap used
(common/mremap.h)
- buf = clickhouse_mremap(buf, old_size, new_size, MREMAP_MAYMOVE,
PROT_READ | PROT_WRITE,
- mmap_flags, -1, 0);
- if (MAP_FAILED == buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot mremap memory
chunk from {} to {}.",
- old_size, new_size));
- }
+ buf = new_buf;
+ if constexpr (clear_memory)
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ } else if (old_size >= doris::config::mmap_threshold &&
+ new_size >= doris::config::mmap_threshold) {
+ /// Resize mmap'd memory region.
+ // On apple and freebsd self-implemented mremap used
(common/mremap.h)
+ buf = clickhouse_mremap(buf, old_size, new_size,
MREMAP_MAYMOVE,
+ PROT_READ | PROT_WRITE, mmap_flags,
-1, 0);
+ if (MAP_FAILED == buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(
+ fmt::format("Allocator: Cannot mremap memory chunk
from {} to {}.",
+ old_size, new_size));
+ }
- /// No need for zero-fill, because mmap guarantees it.
+ /// No need for zero-fill, because mmap guarantees it.
- if constexpr (mmap_populate) {
- // MAP_POPULATE seems have no effect for mremap as for mmap,
- // Clear enlarged memory range explicitly to pre-fault the
pages
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- }
- } else {
- // Big allocs that requires a copy.
- void* new_buf = alloc(new_size, alignment);
- memcpy(new_buf, buf, std::min(old_size, new_size));
+ if constexpr (mmap_populate) {
+ // MAP_POPULATE seems have no effect for mremap as for
mmap,
+ // Clear enlarged memory range explicitly to pre-fault the
pages
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ }
+ } else {
+ // Big allocs that requires a copy.
+ void* new_buf = alloc(new_size, alignment);
+ memcpy(new_buf, buf, std::min(old_size, new_size));
#ifndef NDEBUG
- add_address_sanitizers(new_buf, new_size);
- remove_address_sanitizers(buf, old_size);
+ add_address_sanitizers(new_buf, new_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- free(buf, old_size);
- buf = new_buf;
- }
+ free(buf, old_size);
+ buf = new_buf;
+ }
- return buf;
- }
+ return buf;
+ }
-protected:
- static constexpr size_t get_stack_threshold() { return 0; }
+ protected:
+ static constexpr size_t get_stack_threshold() {
+ return 0;
+ }
- static constexpr bool clear_memory = clear_memory_;
+ static constexpr bool clear_memory = clear_memory_;
- // Freshly mmapped pages are copy-on-write references to a global zero
page.
- // On the first write, a page fault occurs, and an actual writable page is
- // allocated. If we are going to use this memory soon, such as when
resizing
- // hash tables, it makes sense to pre-fault the pages by passing
- // MAP_POPULATE to mmap(). This takes some time, but should be faster
- // overall than having a hot loop interrupted by page faults.
- // It is only supported on Linux.
- static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
+ // Freshly mmapped pages are copy-on-write references to a global zero
page.
+ // On the first write, a page fault occurs, and an actual writable
page is
+ // allocated. If we are going to use this memory soon, such as when
resizing
+ // hash tables, it makes sense to pre-fault the pages by passing
+ // MAP_POPULATE to mmap(). This takes some time, but should be faster
+ // overall than having a hot loop interrupted by page faults.
+ // It is only supported on Linux.
+ static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
#if defined(OS_LINUX)
- | (mmap_populate ? MAP_POPULATE : 0)
+ | (mmap_populate ? MAP_POPULATE : 0)
#endif
- ;
-};
+ ;
+ };
-/** Allocator with optimization to place small memory ranges in automatic
memory.
+ /** Allocator with optimization to place small memory ranges in automatic
memory.
*/
-template <typename Base, size_t N, size_t Alignment>
-class AllocatorWithStackMemory : private Base {
-private:
- alignas(Alignment) char stack_memory[N];
+ template <typename Base, size_t N, size_t Alignment>
+ class AllocatorWithStackMemory : private Base {
+ private:
+ alignas(Alignment) char stack_memory[N];
+
+ public:
+ /// Do not use boost::noncopyable to avoid the warning about direct
base
+ /// being inaccessible due to ambiguity, when derived classes are also
+ /// noncopiable (-Winaccessible-base).
+ AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
+ AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
+ AllocatorWithStackMemory() = default;
+ ~AllocatorWithStackMemory() = default;
+
+ void* alloc(size_t size) {
+ if (size <= N) {
+ if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
Review Comment:
warning: statement should be inside braces
[readability-braces-around-statements]
```suggestion
if constexpr (Base::clear_memory) { memset(stack_memory, 0,
N);
}
```
##########
be/src/vec/common/allocator.h:
##########
@@ -117,187 +237,205 @@
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot mmap {}.",
size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
/// No need for zero-fill, because mmap guarantees it.
} else {
if (alignment <= MALLOC_MIN_ALIGNMENT) {
if constexpr (clear_memory)
- buf = ::calloc(size, 1);
+ buf = MemoryAllocator::calloc(size, 1);
else
- buf = ::malloc(size);
+ buf = MemoryAllocator::malloc(size);
if (nullptr == buf) {
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot malloc
{}.", size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
} else {
buf = nullptr;
- int res = posix_memalign(&buf, alignment, size);
+ int res = MemoryAllocator::posix_memalign(&buf, alignment,
size);
if (0 != res) {
release_memory(size);
throw_bad_alloc(
fmt::format("Cannot allocate memory
(posix_memalign) {}.", size));
}
+
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
-
- if constexpr (clear_memory) memset(buf, 0, size);
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ consume_memory(record_size - size);
+ }
+ return buf;
}
- return buf;
- }
- /// Free memory range.
- void free(void* buf, size_t size) {
- if (use_mmap && size >= doris::config::mmap_threshold) {
- if (0 != munmap(buf, size)) {
- throw_bad_alloc(fmt::format("Allocator: Cannot munmap {}.",
size));
- }
- } else {
+ /// Free memory range.
+ void free(void* buf, size_t size) {
+ if (use_mmap && size >= doris::config::mmap_threshold) {
+ if (0 != munmap(buf, size)) {
+ throw_bad_alloc(fmt::format("Allocator: Cannot munmap
{}.", size));
+ }
+ } else {
#ifndef NDEBUG
- remove_address_sanitizers(buf, size);
+ remove_address_sanitizers(buf, size);
#endif
- ::free(buf);
+ MemoryAllocator::free(buf);
+ }
+ release_memory(size);
+ }
+
+ void release_unused() {
+ MemoryAllocator::release_unused();
}
- release_memory(size);
- }
- /** Enlarge memory range.
+ /** Enlarge memory range.
* Data from old range is moved to the beginning of new range.
* Address of memory range could change.
*/
- void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
- if (old_size == new_size) {
- /// nothing to do.
- /// BTW, it's not possible to change alignment while doing realloc.
- return buf;
- }
- memory_check(new_size);
- consume_memory(new_size - old_size);
+ void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
+ if (old_size == new_size) {
+ /// nothing to do.
+ /// BTW, it's not possible to change alignment while doing
realloc.
+ return buf;
+ }
+ memory_check(new_size);
+ consume_memory(new_size - old_size);
- if (!use_mmap ||
- (old_size < doris::config::mmap_threshold && new_size <
doris::config::mmap_threshold &&
- alignment <= MALLOC_MIN_ALIGNMENT)) {
+ if (!use_mmap ||
+ (old_size < doris::config::mmap_threshold &&
+ new_size < doris::config::mmap_threshold && alignment <=
MALLOC_MIN_ALIGNMENT)) {
#ifndef NDEBUG
- remove_address_sanitizers(buf, old_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- /// Resize malloc'd memory region with no special alignment
requirement.
- void* new_buf = ::realloc(buf, new_size);
- if (nullptr == new_buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot realloc from {}
to {}.", old_size,
- new_size));
- }
+ /// Resize malloc'd memory region with no special alignment
requirement.
+ void* new_buf = MemoryAllocator::realloc(buf, new_size);
+ if (nullptr == new_buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(fmt::format("Allocator: Cannot realloc
from {} to {}.",
+ old_size, new_size));
+ }
#ifndef NDEBUG
- add_address_sanitizers(
- new_buf, new_size); // usually, buf addr = new_buf addr,
asan maybe not equal.
+ add_address_sanitizers(
+ new_buf,
+ new_size); // usually, buf addr = new_buf addr, asan
maybe not equal.
#endif
- buf = new_buf;
- if constexpr (clear_memory)
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- } else if (old_size >= doris::config::mmap_threshold &&
- new_size >= doris::config::mmap_threshold) {
- /// Resize mmap'd memory region.
- // On apple and freebsd self-implemented mremap used
(common/mremap.h)
- buf = clickhouse_mremap(buf, old_size, new_size, MREMAP_MAYMOVE,
PROT_READ | PROT_WRITE,
- mmap_flags, -1, 0);
- if (MAP_FAILED == buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot mremap memory
chunk from {} to {}.",
- old_size, new_size));
- }
+ buf = new_buf;
+ if constexpr (clear_memory)
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ } else if (old_size >= doris::config::mmap_threshold &&
+ new_size >= doris::config::mmap_threshold) {
+ /// Resize mmap'd memory region.
+ // On apple and freebsd self-implemented mremap used
(common/mremap.h)
+ buf = clickhouse_mremap(buf, old_size, new_size,
MREMAP_MAYMOVE,
+ PROT_READ | PROT_WRITE, mmap_flags,
-1, 0);
+ if (MAP_FAILED == buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(
+ fmt::format("Allocator: Cannot mremap memory chunk
from {} to {}.",
+ old_size, new_size));
+ }
- /// No need for zero-fill, because mmap guarantees it.
+ /// No need for zero-fill, because mmap guarantees it.
- if constexpr (mmap_populate) {
- // MAP_POPULATE seems have no effect for mremap as for mmap,
- // Clear enlarged memory range explicitly to pre-fault the
pages
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- }
- } else {
- // Big allocs that requires a copy.
- void* new_buf = alloc(new_size, alignment);
- memcpy(new_buf, buf, std::min(old_size, new_size));
+ if constexpr (mmap_populate) {
+ // MAP_POPULATE seems have no effect for mremap as for
mmap,
+ // Clear enlarged memory range explicitly to pre-fault the
pages
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ }
+ } else {
+ // Big allocs that requires a copy.
+ void* new_buf = alloc(new_size, alignment);
+ memcpy(new_buf, buf, std::min(old_size, new_size));
#ifndef NDEBUG
- add_address_sanitizers(new_buf, new_size);
- remove_address_sanitizers(buf, old_size);
+ add_address_sanitizers(new_buf, new_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- free(buf, old_size);
- buf = new_buf;
- }
+ free(buf, old_size);
+ buf = new_buf;
+ }
- return buf;
- }
+ return buf;
+ }
-protected:
- static constexpr size_t get_stack_threshold() { return 0; }
+ protected:
+ static constexpr size_t get_stack_threshold() {
+ return 0;
+ }
- static constexpr bool clear_memory = clear_memory_;
+ static constexpr bool clear_memory = clear_memory_;
- // Freshly mmapped pages are copy-on-write references to a global zero
page.
- // On the first write, a page fault occurs, and an actual writable page is
- // allocated. If we are going to use this memory soon, such as when
resizing
- // hash tables, it makes sense to pre-fault the pages by passing
- // MAP_POPULATE to mmap(). This takes some time, but should be faster
- // overall than having a hot loop interrupted by page faults.
- // It is only supported on Linux.
- static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
+ // Freshly mmapped pages are copy-on-write references to a global zero
page.
+ // On the first write, a page fault occurs, and an actual writable
page is
+ // allocated. If we are going to use this memory soon, such as when
resizing
+ // hash tables, it makes sense to pre-fault the pages by passing
+ // MAP_POPULATE to mmap(). This takes some time, but should be faster
+ // overall than having a hot loop interrupted by page faults.
+ // It is only supported on Linux.
+ static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
#if defined(OS_LINUX)
- | (mmap_populate ? MAP_POPULATE : 0)
+ | (mmap_populate ? MAP_POPULATE : 0)
#endif
- ;
-};
+ ;
+ };
-/** Allocator with optimization to place small memory ranges in automatic
memory.
+ /** Allocator with optimization to place small memory ranges in automatic
memory.
*/
-template <typename Base, size_t N, size_t Alignment>
-class AllocatorWithStackMemory : private Base {
-private:
- alignas(Alignment) char stack_memory[N];
+ template <typename Base, size_t N, size_t Alignment>
+ class AllocatorWithStackMemory : private Base {
+ private:
+ alignas(Alignment) char stack_memory[N];
+
+ public:
+ /// Do not use boost::noncopyable to avoid the warning about direct
base
+ /// being inaccessible due to ambiguity, when derived classes are also
+ /// noncopiable (-Winaccessible-base).
+ AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
+ AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
+ AllocatorWithStackMemory() = default;
+ ~AllocatorWithStackMemory() = default;
+
+ void* alloc(size_t size) {
+ if (size <= N) {
+ if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
+ return stack_memory;
+ }
-public:
- /// Do not use boost::noncopyable to avoid the warning about direct base
- /// being inaccessible due to ambiguity, when derived classes are also
- /// noncopiable (-Winaccessible-base).
- AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
- AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
- AllocatorWithStackMemory() = default;
- ~AllocatorWithStackMemory() = default;
-
- void* alloc(size_t size) {
- if (size <= N) {
- if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
- return stack_memory;
+ return Base::alloc(size, Alignment);
}
- return Base::alloc(size, Alignment);
- }
-
- void free(void* buf, size_t size) {
- if (size > N) Base::free(buf, size);
- }
+ void free(void* buf, size_t size) {
+ if (size > N) Base::free(buf, size);
+ }
- void* realloc(void* buf, size_t old_size, size_t new_size) {
- /// Was in stack_memory, will remain there.
- if (new_size <= N) return buf;
+ void* realloc(void* buf, size_t old_size, size_t new_size) {
+ /// Was in stack_memory, will remain there.
+ if (new_size <= N) return buf;
- /// Already was big enough to not fit in stack_memory.
- if (old_size > N) return Base::realloc(buf, old_size, new_size,
Alignment);
+ /// Already was big enough to not fit in stack_memory.
+ if (old_size > N) return Base::realloc(buf, old_size, new_size,
Alignment);
Review Comment:
warning: statement should be inside braces
[readability-braces-around-statements]
```suggestion
if (old_size > N) { return Base::realloc(buf, old_size,
new_size, Alignment);
}
```
##########
be/src/vec/common/allocator.h:
##########
@@ -23,6 +23,10 @@
// TODO: Readable
#include <fmt/format.h>
Review Comment:
warning: 'fmt/format.h' file not found [clang-diagnostic-error]
```cpp
#include <fmt/format.h>
^
```
##########
be/src/vec/exec/format/parquet/arrow_memory_pool.cpp:
##########
@@ -0,0 +1,74 @@
+// 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 "vec/exec/format/parquet/arrow_memory_pool.h"
+
+#include "glog/logging.h"
+
+namespace doris::vectorized {
+
+// A static piece of memory for 0-size allocations, so as to return
+// an aligned non-null pointer. Note the correct value for DebugAllocator
+// checks is hardcoded.
+alignas(kDefaultBufferAlignment) int64_t zero_size_area[1] = {kDebugXorSuffix};
+
+arrow::Status ArrowAllocator::allocate_aligned(int64_t size, int64_t
alignment, uint8_t** out) {
+ if (size == 0) {
+ *out = kZeroSizeArea;
+ return arrow::Status::OK();
+ }
+ *out = reinterpret_cast<uint8_t*>(_allocator.alloc(size, alignment));
+ if (*out == nullptr) {
+ return arrow::Status::OutOfMemory("malloc of size ", size, " failed");
+ }
+ return arrow::Status::OK();
+}
+
+arrow::Status ArrowAllocator::reallocate_aligned(int64_t old_size, int64_t
new_size,
+ int64_t alignment, uint8_t**
ptr) {
+ uint8_t* previous_ptr = *ptr;
+ if (previous_ptr == kZeroSizeArea) {
+ DCHECK_EQ(old_size, 0);
+ return allocate_aligned(new_size, alignment, ptr);
+ }
+ if (new_size == 0) {
+ deallocate_aligned(previous_ptr, old_size, alignment);
+ *ptr = kZeroSizeArea;
+ return arrow::Status::OK();
+ }
+ *ptr = reinterpret_cast<uint8_t*>(_allocator.realloc(*ptr,
static_cast<size_t>(old_size),
+
static_cast<size_t>(new_size), alignment));
+ if (*ptr == nullptr) {
+ *ptr = previous_ptr;
+ return arrow::Status::OutOfMemory("realloc of size ", new_size, "
failed");
+ }
+ return arrow::Status::OK();
+}
+
+void ArrowAllocator::deallocate_aligned(uint8_t* ptr, int64_t size, int64_t
alignment) {
Review Comment:
warning: pointer parameter 'ptr' can be pointer to const
[readability-non-const-parameter]
```suggestion
void ArrowAllocator::deallocate_aligned(const uint8_t* ptr, int64_t size,
int64_t alignment) {
```
be/src/vec/exec/format/parquet/arrow_memory_pool.h:47:
```diff
- void deallocate_aligned(uint8_t* ptr, int64_t size, int64_t alignment);
+ void deallocate_aligned(const uint8_t* ptr, int64_t size, int64_t
alignment);
```
##########
be/src/vec/common/allocator.h:
##########
@@ -117,187 +237,205 @@
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot mmap {}.",
size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
/// No need for zero-fill, because mmap guarantees it.
} else {
if (alignment <= MALLOC_MIN_ALIGNMENT) {
if constexpr (clear_memory)
- buf = ::calloc(size, 1);
+ buf = MemoryAllocator::calloc(size, 1);
else
- buf = ::malloc(size);
+ buf = MemoryAllocator::malloc(size);
if (nullptr == buf) {
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot malloc
{}.", size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
} else {
buf = nullptr;
- int res = posix_memalign(&buf, alignment, size);
+ int res = MemoryAllocator::posix_memalign(&buf, alignment,
size);
if (0 != res) {
release_memory(size);
throw_bad_alloc(
fmt::format("Cannot allocate memory
(posix_memalign) {}.", size));
}
+
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
-
- if constexpr (clear_memory) memset(buf, 0, size);
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ consume_memory(record_size - size);
+ }
+ return buf;
}
- return buf;
- }
- /// Free memory range.
- void free(void* buf, size_t size) {
- if (use_mmap && size >= doris::config::mmap_threshold) {
- if (0 != munmap(buf, size)) {
- throw_bad_alloc(fmt::format("Allocator: Cannot munmap {}.",
size));
- }
- } else {
+ /// Free memory range.
+ void free(void* buf, size_t size) {
+ if (use_mmap && size >= doris::config::mmap_threshold) {
+ if (0 != munmap(buf, size)) {
+ throw_bad_alloc(fmt::format("Allocator: Cannot munmap
{}.", size));
+ }
+ } else {
#ifndef NDEBUG
- remove_address_sanitizers(buf, size);
+ remove_address_sanitizers(buf, size);
#endif
- ::free(buf);
+ MemoryAllocator::free(buf);
+ }
+ release_memory(size);
+ }
+
+ void release_unused() {
+ MemoryAllocator::release_unused();
}
- release_memory(size);
- }
- /** Enlarge memory range.
+ /** Enlarge memory range.
* Data from old range is moved to the beginning of new range.
* Address of memory range could change.
*/
- void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
- if (old_size == new_size) {
- /// nothing to do.
- /// BTW, it's not possible to change alignment while doing realloc.
- return buf;
- }
- memory_check(new_size);
- consume_memory(new_size - old_size);
+ void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
+ if (old_size == new_size) {
+ /// nothing to do.
+ /// BTW, it's not possible to change alignment while doing
realloc.
+ return buf;
+ }
+ memory_check(new_size);
+ consume_memory(new_size - old_size);
- if (!use_mmap ||
- (old_size < doris::config::mmap_threshold && new_size <
doris::config::mmap_threshold &&
- alignment <= MALLOC_MIN_ALIGNMENT)) {
+ if (!use_mmap ||
+ (old_size < doris::config::mmap_threshold &&
+ new_size < doris::config::mmap_threshold && alignment <=
MALLOC_MIN_ALIGNMENT)) {
#ifndef NDEBUG
- remove_address_sanitizers(buf, old_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- /// Resize malloc'd memory region with no special alignment
requirement.
- void* new_buf = ::realloc(buf, new_size);
- if (nullptr == new_buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot realloc from {}
to {}.", old_size,
- new_size));
- }
+ /// Resize malloc'd memory region with no special alignment
requirement.
+ void* new_buf = MemoryAllocator::realloc(buf, new_size);
+ if (nullptr == new_buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(fmt::format("Allocator: Cannot realloc
from {} to {}.",
+ old_size, new_size));
+ }
#ifndef NDEBUG
- add_address_sanitizers(
- new_buf, new_size); // usually, buf addr = new_buf addr,
asan maybe not equal.
+ add_address_sanitizers(
+ new_buf,
+ new_size); // usually, buf addr = new_buf addr, asan
maybe not equal.
#endif
- buf = new_buf;
- if constexpr (clear_memory)
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- } else if (old_size >= doris::config::mmap_threshold &&
- new_size >= doris::config::mmap_threshold) {
- /// Resize mmap'd memory region.
- // On apple and freebsd self-implemented mremap used
(common/mremap.h)
- buf = clickhouse_mremap(buf, old_size, new_size, MREMAP_MAYMOVE,
PROT_READ | PROT_WRITE,
- mmap_flags, -1, 0);
- if (MAP_FAILED == buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot mremap memory
chunk from {} to {}.",
- old_size, new_size));
- }
+ buf = new_buf;
+ if constexpr (clear_memory)
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ } else if (old_size >= doris::config::mmap_threshold &&
+ new_size >= doris::config::mmap_threshold) {
+ /// Resize mmap'd memory region.
+ // On apple and freebsd self-implemented mremap used
(common/mremap.h)
+ buf = clickhouse_mremap(buf, old_size, new_size,
MREMAP_MAYMOVE,
+ PROT_READ | PROT_WRITE, mmap_flags,
-1, 0);
+ if (MAP_FAILED == buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(
+ fmt::format("Allocator: Cannot mremap memory chunk
from {} to {}.",
+ old_size, new_size));
+ }
- /// No need for zero-fill, because mmap guarantees it.
+ /// No need for zero-fill, because mmap guarantees it.
- if constexpr (mmap_populate) {
- // MAP_POPULATE seems have no effect for mremap as for mmap,
- // Clear enlarged memory range explicitly to pre-fault the
pages
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- }
- } else {
- // Big allocs that requires a copy.
- void* new_buf = alloc(new_size, alignment);
- memcpy(new_buf, buf, std::min(old_size, new_size));
+ if constexpr (mmap_populate) {
+ // MAP_POPULATE seems have no effect for mremap as for
mmap,
+ // Clear enlarged memory range explicitly to pre-fault the
pages
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ }
+ } else {
+ // Big allocs that requires a copy.
+ void* new_buf = alloc(new_size, alignment);
+ memcpy(new_buf, buf, std::min(old_size, new_size));
#ifndef NDEBUG
- add_address_sanitizers(new_buf, new_size);
- remove_address_sanitizers(buf, old_size);
+ add_address_sanitizers(new_buf, new_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- free(buf, old_size);
- buf = new_buf;
- }
+ free(buf, old_size);
+ buf = new_buf;
+ }
- return buf;
- }
+ return buf;
+ }
-protected:
- static constexpr size_t get_stack_threshold() { return 0; }
+ protected:
+ static constexpr size_t get_stack_threshold() {
+ return 0;
+ }
- static constexpr bool clear_memory = clear_memory_;
+ static constexpr bool clear_memory = clear_memory_;
- // Freshly mmapped pages are copy-on-write references to a global zero
page.
- // On the first write, a page fault occurs, and an actual writable page is
- // allocated. If we are going to use this memory soon, such as when
resizing
- // hash tables, it makes sense to pre-fault the pages by passing
- // MAP_POPULATE to mmap(). This takes some time, but should be faster
- // overall than having a hot loop interrupted by page faults.
- // It is only supported on Linux.
- static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
+ // Freshly mmapped pages are copy-on-write references to a global zero
page.
+ // On the first write, a page fault occurs, and an actual writable
page is
+ // allocated. If we are going to use this memory soon, such as when
resizing
+ // hash tables, it makes sense to pre-fault the pages by passing
+ // MAP_POPULATE to mmap(). This takes some time, but should be faster
+ // overall than having a hot loop interrupted by page faults.
+ // It is only supported on Linux.
+ static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
#if defined(OS_LINUX)
- | (mmap_populate ? MAP_POPULATE : 0)
+ | (mmap_populate ? MAP_POPULATE : 0)
#endif
- ;
-};
+ ;
+ };
-/** Allocator with optimization to place small memory ranges in automatic
memory.
+ /** Allocator with optimization to place small memory ranges in automatic
memory.
*/
-template <typename Base, size_t N, size_t Alignment>
-class AllocatorWithStackMemory : private Base {
-private:
- alignas(Alignment) char stack_memory[N];
+ template <typename Base, size_t N, size_t Alignment>
+ class AllocatorWithStackMemory : private Base {
+ private:
+ alignas(Alignment) char stack_memory[N];
+
+ public:
+ /// Do not use boost::noncopyable to avoid the warning about direct
base
+ /// being inaccessible due to ambiguity, when derived classes are also
+ /// noncopiable (-Winaccessible-base).
+ AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
+ AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
+ AllocatorWithStackMemory() = default;
+ ~AllocatorWithStackMemory() = default;
+
+ void* alloc(size_t size) {
+ if (size <= N) {
+ if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
+ return stack_memory;
+ }
-public:
- /// Do not use boost::noncopyable to avoid the warning about direct base
- /// being inaccessible due to ambiguity, when derived classes are also
- /// noncopiable (-Winaccessible-base).
- AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
- AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
- AllocatorWithStackMemory() = default;
- ~AllocatorWithStackMemory() = default;
-
- void* alloc(size_t size) {
- if (size <= N) {
- if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
- return stack_memory;
+ return Base::alloc(size, Alignment);
}
- return Base::alloc(size, Alignment);
- }
-
- void free(void* buf, size_t size) {
- if (size > N) Base::free(buf, size);
- }
+ void free(void* buf, size_t size) {
+ if (size > N) Base::free(buf, size);
+ }
- void* realloc(void* buf, size_t old_size, size_t new_size) {
- /// Was in stack_memory, will remain there.
- if (new_size <= N) return buf;
+ void* realloc(void* buf, size_t old_size, size_t new_size) {
+ /// Was in stack_memory, will remain there.
+ if (new_size <= N) return buf;
Review Comment:
warning: statement should be inside braces
[readability-braces-around-statements]
```suggestion
if (new_size <= N) { return buf;
}
```
##########
be/src/vec/exec/format/parquet/arrow_memory_pool.h:
##########
@@ -0,0 +1,199 @@
+// 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.
+
+#pragma once
+
+#include "arrow/memory_pool.h"
Review Comment:
warning: 'arrow/memory_pool.h' file not found [clang-diagnostic-error]
```cpp
#include "arrow/memory_pool.h"
^
```
##########
be/src/vec/common/allocator.h:
##########
@@ -117,187 +237,205 @@
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot mmap {}.",
size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
/// No need for zero-fill, because mmap guarantees it.
} else {
if (alignment <= MALLOC_MIN_ALIGNMENT) {
if constexpr (clear_memory)
- buf = ::calloc(size, 1);
+ buf = MemoryAllocator::calloc(size, 1);
else
- buf = ::malloc(size);
+ buf = MemoryAllocator::malloc(size);
if (nullptr == buf) {
release_memory(size);
throw_bad_alloc(fmt::format("Allocator: Cannot malloc
{}.", size));
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
} else {
buf = nullptr;
- int res = posix_memalign(&buf, alignment, size);
+ int res = MemoryAllocator::posix_memalign(&buf, alignment,
size);
if (0 != res) {
release_memory(size);
throw_bad_alloc(
fmt::format("Cannot allocate memory
(posix_memalign) {}.", size));
}
+
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ record_size = MemoryAllocator::allocated_size(buf);
+ }
#ifndef NDEBUG
- add_address_sanitizers(buf, size);
+ add_address_sanitizers(buf, record_size);
#endif
-
- if constexpr (clear_memory) memset(buf, 0, size);
}
+ if constexpr (MemoryAllocator::need_record_actual_size()) {
+ consume_memory(record_size - size);
+ }
+ return buf;
}
- return buf;
- }
- /// Free memory range.
- void free(void* buf, size_t size) {
- if (use_mmap && size >= doris::config::mmap_threshold) {
- if (0 != munmap(buf, size)) {
- throw_bad_alloc(fmt::format("Allocator: Cannot munmap {}.",
size));
- }
- } else {
+ /// Free memory range.
+ void free(void* buf, size_t size) {
+ if (use_mmap && size >= doris::config::mmap_threshold) {
+ if (0 != munmap(buf, size)) {
+ throw_bad_alloc(fmt::format("Allocator: Cannot munmap
{}.", size));
+ }
+ } else {
#ifndef NDEBUG
- remove_address_sanitizers(buf, size);
+ remove_address_sanitizers(buf, size);
#endif
- ::free(buf);
+ MemoryAllocator::free(buf);
+ }
+ release_memory(size);
+ }
+
+ void release_unused() {
+ MemoryAllocator::release_unused();
}
- release_memory(size);
- }
- /** Enlarge memory range.
+ /** Enlarge memory range.
* Data from old range is moved to the beginning of new range.
* Address of memory range could change.
*/
- void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
- if (old_size == new_size) {
- /// nothing to do.
- /// BTW, it's not possible to change alignment while doing realloc.
- return buf;
- }
- memory_check(new_size);
- consume_memory(new_size - old_size);
+ void* realloc_impl(void* buf, size_t old_size, size_t new_size, size_t
alignment = 0) {
+ if (old_size == new_size) {
+ /// nothing to do.
+ /// BTW, it's not possible to change alignment while doing
realloc.
+ return buf;
+ }
+ memory_check(new_size);
+ consume_memory(new_size - old_size);
- if (!use_mmap ||
- (old_size < doris::config::mmap_threshold && new_size <
doris::config::mmap_threshold &&
- alignment <= MALLOC_MIN_ALIGNMENT)) {
+ if (!use_mmap ||
+ (old_size < doris::config::mmap_threshold &&
+ new_size < doris::config::mmap_threshold && alignment <=
MALLOC_MIN_ALIGNMENT)) {
#ifndef NDEBUG
- remove_address_sanitizers(buf, old_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- /// Resize malloc'd memory region with no special alignment
requirement.
- void* new_buf = ::realloc(buf, new_size);
- if (nullptr == new_buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot realloc from {}
to {}.", old_size,
- new_size));
- }
+ /// Resize malloc'd memory region with no special alignment
requirement.
+ void* new_buf = MemoryAllocator::realloc(buf, new_size);
+ if (nullptr == new_buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(fmt::format("Allocator: Cannot realloc
from {} to {}.",
+ old_size, new_size));
+ }
#ifndef NDEBUG
- add_address_sanitizers(
- new_buf, new_size); // usually, buf addr = new_buf addr,
asan maybe not equal.
+ add_address_sanitizers(
+ new_buf,
+ new_size); // usually, buf addr = new_buf addr, asan
maybe not equal.
#endif
- buf = new_buf;
- if constexpr (clear_memory)
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- } else if (old_size >= doris::config::mmap_threshold &&
- new_size >= doris::config::mmap_threshold) {
- /// Resize mmap'd memory region.
- // On apple and freebsd self-implemented mremap used
(common/mremap.h)
- buf = clickhouse_mremap(buf, old_size, new_size, MREMAP_MAYMOVE,
PROT_READ | PROT_WRITE,
- mmap_flags, -1, 0);
- if (MAP_FAILED == buf) {
- release_memory(new_size - old_size);
- throw_bad_alloc(fmt::format("Allocator: Cannot mremap memory
chunk from {} to {}.",
- old_size, new_size));
- }
+ buf = new_buf;
+ if constexpr (clear_memory)
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ } else if (old_size >= doris::config::mmap_threshold &&
+ new_size >= doris::config::mmap_threshold) {
+ /// Resize mmap'd memory region.
+ // On apple and freebsd self-implemented mremap used
(common/mremap.h)
+ buf = clickhouse_mremap(buf, old_size, new_size,
MREMAP_MAYMOVE,
+ PROT_READ | PROT_WRITE, mmap_flags,
-1, 0);
+ if (MAP_FAILED == buf) {
+ release_memory(new_size - old_size);
+ throw_bad_alloc(
+ fmt::format("Allocator: Cannot mremap memory chunk
from {} to {}.",
+ old_size, new_size));
+ }
- /// No need for zero-fill, because mmap guarantees it.
+ /// No need for zero-fill, because mmap guarantees it.
- if constexpr (mmap_populate) {
- // MAP_POPULATE seems have no effect for mremap as for mmap,
- // Clear enlarged memory range explicitly to pre-fault the
pages
- if (new_size > old_size)
- memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
- }
- } else {
- // Big allocs that requires a copy.
- void* new_buf = alloc(new_size, alignment);
- memcpy(new_buf, buf, std::min(old_size, new_size));
+ if constexpr (mmap_populate) {
+ // MAP_POPULATE seems have no effect for mremap as for
mmap,
+ // Clear enlarged memory range explicitly to pre-fault the
pages
+ if (new_size > old_size)
+ memset(reinterpret_cast<char*>(buf) + old_size, 0,
new_size - old_size);
+ }
+ } else {
+ // Big allocs that requires a copy.
+ void* new_buf = alloc(new_size, alignment);
+ memcpy(new_buf, buf, std::min(old_size, new_size));
#ifndef NDEBUG
- add_address_sanitizers(new_buf, new_size);
- remove_address_sanitizers(buf, old_size);
+ add_address_sanitizers(new_buf, new_size);
+ remove_address_sanitizers(buf, old_size);
#endif
- free(buf, old_size);
- buf = new_buf;
- }
+ free(buf, old_size);
+ buf = new_buf;
+ }
- return buf;
- }
+ return buf;
+ }
-protected:
- static constexpr size_t get_stack_threshold() { return 0; }
+ protected:
+ static constexpr size_t get_stack_threshold() {
+ return 0;
+ }
- static constexpr bool clear_memory = clear_memory_;
+ static constexpr bool clear_memory = clear_memory_;
- // Freshly mmapped pages are copy-on-write references to a global zero
page.
- // On the first write, a page fault occurs, and an actual writable page is
- // allocated. If we are going to use this memory soon, such as when
resizing
- // hash tables, it makes sense to pre-fault the pages by passing
- // MAP_POPULATE to mmap(). This takes some time, but should be faster
- // overall than having a hot loop interrupted by page faults.
- // It is only supported on Linux.
- static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
+ // Freshly mmapped pages are copy-on-write references to a global zero
page.
+ // On the first write, a page fault occurs, and an actual writable
page is
+ // allocated. If we are going to use this memory soon, such as when
resizing
+ // hash tables, it makes sense to pre-fault the pages by passing
+ // MAP_POPULATE to mmap(). This takes some time, but should be faster
+ // overall than having a hot loop interrupted by page faults.
+ // It is only supported on Linux.
+ static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
#if defined(OS_LINUX)
- | (mmap_populate ? MAP_POPULATE : 0)
+ | (mmap_populate ? MAP_POPULATE : 0)
#endif
- ;
-};
+ ;
+ };
-/** Allocator with optimization to place small memory ranges in automatic
memory.
+ /** Allocator with optimization to place small memory ranges in automatic
memory.
*/
-template <typename Base, size_t N, size_t Alignment>
-class AllocatorWithStackMemory : private Base {
-private:
- alignas(Alignment) char stack_memory[N];
+ template <typename Base, size_t N, size_t Alignment>
+ class AllocatorWithStackMemory : private Base {
+ private:
+ alignas(Alignment) char stack_memory[N];
+
+ public:
+ /// Do not use boost::noncopyable to avoid the warning about direct
base
+ /// being inaccessible due to ambiguity, when derived classes are also
+ /// noncopiable (-Winaccessible-base).
+ AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
+ AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
+ AllocatorWithStackMemory() = default;
+ ~AllocatorWithStackMemory() = default;
+
+ void* alloc(size_t size) {
+ if (size <= N) {
+ if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
+ return stack_memory;
+ }
-public:
- /// Do not use boost::noncopyable to avoid the warning about direct base
- /// being inaccessible due to ambiguity, when derived classes are also
- /// noncopiable (-Winaccessible-base).
- AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete;
- AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) =
delete;
- AllocatorWithStackMemory() = default;
- ~AllocatorWithStackMemory() = default;
-
- void* alloc(size_t size) {
- if (size <= N) {
- if constexpr (Base::clear_memory) memset(stack_memory, 0, N);
- return stack_memory;
+ return Base::alloc(size, Alignment);
}
- return Base::alloc(size, Alignment);
- }
-
- void free(void* buf, size_t size) {
- if (size > N) Base::free(buf, size);
- }
+ void free(void* buf, size_t size) {
+ if (size > N) Base::free(buf, size);
Review Comment:
warning: statement should be inside braces
[readability-braces-around-statements]
```suggestion
if (size > N) { Base::free(buf, size);
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]