Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // This file is copied from |
18 | | // https://github.com/ClickHouse/ClickHouse/blob/master/src/Common/Allocator.h |
19 | | // and modified by Doris |
20 | | |
21 | | #pragma once |
22 | | |
23 | | // TODO: Readable |
24 | | |
25 | | #include <fmt/format.h> |
26 | | #if defined(USE_JEMALLOC) |
27 | | #include <jemalloc/jemalloc.h> |
28 | | #endif // defined(USE_JEMALLOC) |
29 | | |
30 | | #ifdef __APPLE__ |
31 | | #include <malloc/malloc.h> |
32 | | #define GET_MALLOC_SIZE(ptr) malloc_size(ptr) |
33 | | #else |
34 | | #include <malloc.h> |
35 | 0 | #define GET_MALLOC_SIZE(ptr) malloc_usable_size(ptr) |
36 | | #endif |
37 | | #include <stdint.h> |
38 | | #include <string.h> |
39 | | |
40 | | #include "common/config.h" |
41 | | #include "common/status.h" |
42 | | #include "util/sse_util.hpp" |
43 | | |
44 | | #ifdef NDEBUG |
45 | | #define ALLOCATOR_ASLR 0 |
46 | | #else |
47 | | #define ALLOCATOR_ASLR 1 |
48 | | #endif |
49 | | |
50 | | #include <sys/mman.h> |
51 | | |
52 | | #include <algorithm> |
53 | | #include <cstdlib> |
54 | | #include <string> |
55 | | |
56 | | #include "common/compiler_util.h" // IWYU pragma: keep |
57 | | #ifdef THREAD_SANITIZER |
58 | | /// Thread sanitizer does not intercept mremap. The usage of mremap will lead to false positives. |
59 | | #define DISABLE_MREMAP 1 |
60 | | #endif |
61 | | #include "common/exception.h" |
62 | | #include "core/mremap.h" |
63 | | |
64 | | /// Required for older Darwin builds, that lack definition of MAP_ANONYMOUS |
65 | | #ifndef MAP_ANONYMOUS |
66 | | #define MAP_ANONYMOUS MAP_ANON |
67 | | #endif |
68 | | |
69 | | #ifndef __THROW |
70 | | #if __cplusplus |
71 | | #define __THROW noexcept |
72 | | #else |
73 | | #define __THROW |
74 | | #endif |
75 | | #endif |
76 | | |
77 | | namespace doris { |
78 | | static constexpr size_t MMAP_MIN_ALIGNMENT = 4096; |
79 | | static constexpr size_t MALLOC_MIN_ALIGNMENT = 8; |
80 | | |
81 | | // The memory for __int128 should be aligned to 16 bytes. |
82 | | // By the way, in 64-bit system, the address of a block returned by malloc or realloc in GNU systems |
83 | | // is always a multiple of sixteen. (https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html) |
84 | | static constexpr int ALLOCATOR_ALIGNMENT_16 = 16; |
85 | | |
86 | | class MemTrackerLimiter; |
87 | | |
88 | | class DefaultMemoryAllocator { |
89 | | public: |
90 | 2.70M | static void* malloc(size_t size) __THROW { return std::malloc(size); } |
91 | | |
92 | 22.9k | static void* calloc(size_t n, size_t size) __THROW { return std::calloc(n, size); } |
93 | | |
94 | 0 | static constexpr bool need_record_actual_size() { return false; } |
95 | | |
96 | 49.2k | static int posix_memalign(void** ptr, size_t alignment, size_t size) __THROW { |
97 | 49.2k | return ::posix_memalign(ptr, alignment, size); |
98 | 49.2k | } |
99 | | |
100 | 269k | static void* realloc(void* ptr, size_t size) __THROW { return std::realloc(ptr, size); } |
101 | | |
102 | 2.77M | static void free(void* p) __THROW { std::free(p); } |
103 | | |
104 | 0 | static void release_unused() { |
105 | | #if defined(USE_JEMALLOC) |
106 | | jemallctl(fmt::format("arena.{}.purge", MALLCTL_ARENAS_ALL).c_str(), nullptr, nullptr, |
107 | | nullptr, 0); |
108 | | #endif // defined(USE_JEMALLOC) |
109 | 0 | } |
110 | | }; |
111 | | |
112 | | /** It would be better to put these Memory Allocators where they are used, such as in the orc memory pool and arrow memory pool. |
113 | | * But currently allocators use templates in .cpp instead of all in .h, so they can only be placed here. |
114 | | */ |
115 | | class ORCMemoryAllocator { |
116 | | public: |
117 | 0 | static void* malloc(size_t size) __THROW { return reinterpret_cast<char*>(std::malloc(size)); } |
118 | | |
119 | 0 | static void* calloc(size_t n, size_t size) __THROW { return std::calloc(n, size); } |
120 | | |
121 | 0 | static constexpr bool need_record_actual_size() { return true; } |
122 | | |
123 | 0 | static size_t allocated_size(void* ptr) { return GET_MALLOC_SIZE(ptr); } |
124 | | |
125 | 0 | static int posix_memalign(void** ptr, size_t alignment, size_t size) __THROW { |
126 | 0 | return ::posix_memalign(ptr, alignment, size); |
127 | 0 | } |
128 | | |
129 | 0 | static void* realloc(void* ptr, size_t size) __THROW { |
130 | 0 | LOG(FATAL) << "__builtin_unreachable"; |
131 | 0 | __builtin_unreachable(); |
132 | 0 | } |
133 | | |
134 | 0 | static void free(void* p) __THROW { std::free(p); } |
135 | | |
136 | 0 | static void release_unused() {} |
137 | | }; |
138 | | |
139 | | class RecordSizeMemoryAllocator { |
140 | | public: |
141 | 3.48k | static void* malloc(size_t size) __THROW { |
142 | 3.48k | void* p = std::malloc(size); |
143 | 3.48k | if (p) { |
144 | 3.48k | std::lock_guard<std::mutex> lock(_mutex); |
145 | 3.48k | _allocated_sizes[p] = size; |
146 | 3.48k | } |
147 | 3.48k | return p; |
148 | 3.48k | } |
149 | | |
150 | 0 | static void* calloc(size_t n, size_t size) __THROW { |
151 | 0 | void* p = std::calloc(n, size); |
152 | 0 | if (p) { |
153 | 0 | std::lock_guard<std::mutex> lock(_mutex); |
154 | 0 | _allocated_sizes[p] = n * size; |
155 | 0 | } |
156 | 0 | return p; |
157 | 0 | } |
158 | | |
159 | 0 | static constexpr bool need_record_actual_size() { return false; } |
160 | | |
161 | 3.48k | static size_t allocated_size(void* ptr) { |
162 | 3.48k | std::lock_guard<std::mutex> lock(_mutex); |
163 | 3.48k | auto it = _allocated_sizes.find(ptr); |
164 | 3.48k | if (it != _allocated_sizes.end()) { |
165 | 3.48k | return it->second; |
166 | 3.48k | } |
167 | 0 | return 0; |
168 | 3.48k | } |
169 | | |
170 | 0 | static int posix_memalign(void** ptr, size_t alignment, size_t size) __THROW { |
171 | 0 | int ret = ::posix_memalign(ptr, alignment, size); |
172 | 0 | if (ret == 0 && *ptr) { |
173 | 0 | std::lock_guard<std::mutex> lock(_mutex); |
174 | 0 | _allocated_sizes[*ptr] = size; |
175 | 0 | } |
176 | 0 | return ret; |
177 | 0 | } |
178 | | |
179 | 0 | static void* realloc(void* ptr, size_t size) __THROW { |
180 | 0 | std::lock_guard<std::mutex> lock(_mutex); |
181 | |
|
182 | 0 | auto it = _allocated_sizes.find(ptr); |
183 | 0 | if (it != _allocated_sizes.end()) { |
184 | 0 | _allocated_sizes.erase(it); |
185 | 0 | } |
186 | |
|
187 | 0 | void* p = std::realloc(ptr, size); |
188 | |
|
189 | 0 | if (p) { |
190 | 0 | _allocated_sizes[p] = size; |
191 | 0 | } |
192 | |
|
193 | 0 | return p; |
194 | 0 | } |
195 | | |
196 | 3.48k | static void free(void* p) __THROW { |
197 | 3.48k | if (p) { |
198 | 3.48k | std::lock_guard<std::mutex> lock(_mutex); |
199 | 3.48k | _allocated_sizes.erase(p); |
200 | 3.48k | std::free(p); |
201 | 3.48k | } |
202 | 3.48k | } |
203 | | |
204 | 0 | static void release_unused() {} |
205 | | |
206 | | private: |
207 | | static std::unordered_map<void*, size_t> _allocated_sizes; |
208 | | static std::mutex _mutex; |
209 | | }; |
210 | | |
211 | | /** Responsible for allocating / freeing memory. Used, for example, in PODArray, Arena. |
212 | | * Also used in hash tables. |
213 | | * The interface is different from std::allocator |
214 | | * - the presence of the method realloc, which for large chunks of memory uses mremap; |
215 | | * - passing the size into the `free` method; |
216 | | * - by the presence of the `alignment` argument; |
217 | | * - the possibility of zeroing memory (used in hash tables); |
218 | | * - random hint address for mmap |
219 | | * - mmap_threshold for using mmap less or more |
220 | | */ |
221 | | template <bool clear_memory_, bool mmap_populate, bool use_mmap, typename MemoryAllocator, |
222 | | bool check_and_tracking_memory> |
223 | | class Allocator { |
224 | | public: |
225 | | // Allocate memory range. |
226 | | void* alloc(size_t size, size_t alignment = 0); |
227 | | |
228 | | /** Enlarge memory range. |
229 | | * Data from old range is moved to the beginning of new range. |
230 | | * Address of memory range could change. |
231 | | */ |
232 | | void* realloc(void* buf, size_t old_size, size_t new_size, size_t alignment = 0); |
233 | | |
234 | | // Free memory range. |
235 | | void free(void* buf, size_t size) const; |
236 | | |
237 | 0 | void release_unused() { MemoryAllocator::release_unused(); }Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_18ORCMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_18ORCMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb1EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb0EE14release_unusedEv |
238 | | |
239 | | bool sys_memory_exceed(size_t size, std::string* err_msg) const; |
240 | | |
241 | | bool memory_tracker_exceed(size_t size, std::string* err_msg) const; |
242 | | |
243 | | protected: |
244 | 0 | static constexpr size_t get_stack_threshold() { return 0; }Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_22DefaultMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_18ORCMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_18ORCMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb1ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb1ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb1ELb0ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb1ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris9AllocatorILb0ELb0ELb0ENS_25RecordSizeMemoryAllocatorELb0EE19get_stack_thresholdEv |
245 | | |
246 | | static constexpr bool clear_memory = clear_memory_; |
247 | | |
248 | | private: |
249 | | void sys_memory_check(size_t size) const; |
250 | | void memory_tracker_check(size_t size) const; |
251 | | // If sys memory or tracker exceeds the limit, but there is no external catch bad_alloc, |
252 | | // alloc will continue to execute, so the consume memtracker is forced. |
253 | | void memory_check(size_t size) const; |
254 | | void alloc_fault_probability() const; |
255 | | |
256 | | // Increases consumption of this tracker by 'bytes'. |
257 | | // some special cases: |
258 | | // 1. objects that inherit Allocator will not be shared by multiple queries. |
259 | | // non-compliant: page cache, ORC ByteBuffer. |
260 | | // 2. objects that inherit Allocator will only free memory allocated by themselves. |
261 | | // non-compliant: phmap, the memory alloced by an object may be transferred to another object and then free. |
262 | | // 3. the memory tracker in TLS is the same during the construction of objects that inherit Allocator |
263 | | // and during subsequent memory allocation. |
264 | | void consume_memory(size_t size) const; |
265 | | void release_memory(size_t size) const; |
266 | | void throw_bad_alloc(const std::string& err) const; |
267 | | void add_address_sanitizers(void* buf, size_t size) const; |
268 | | void remove_address_sanitizers(void* buf, size_t size) const; |
269 | | |
270 | | // Freshly mmapped pages are copy-on-write references to a global zero page. |
271 | | // On the first write, a page fault occurs, and an actual writable page is |
272 | | // allocated. If we are going to use this memory soon, such as when resizing |
273 | | // hash tables, it makes sense to pre-fault the pages by passing |
274 | | // MAP_POPULATE to mmap(). This takes some time, but should be faster |
275 | | // overall than having a hot loop interrupted by page faults. |
276 | | // It is only supported on Linux. |
277 | | static constexpr int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS |
278 | | #if defined(OS_LINUX) |
279 | | | (mmap_populate ? MAP_POPULATE : 0) |
280 | | #endif |
281 | | ; |
282 | | }; |
283 | | |
284 | | /** Allocator with optimization to place small memory ranges in automatic memory. |
285 | | */ |
286 | | template <typename Base, size_t N, size_t Alignment> |
287 | | class AllocatorWithStackMemory : private Base { |
288 | | private: |
289 | | alignas(Alignment) char stack_memory[N]; |
290 | | |
291 | | public: |
292 | | /// Do not use boost::noncopyable to avoid the warning about direct base |
293 | | /// being inaccessible due to ambiguity, when derived classes are also |
294 | | /// noncopiable (-Winaccessible-base). |
295 | | AllocatorWithStackMemory(const AllocatorWithStackMemory&) = delete; |
296 | | AllocatorWithStackMemory& operator=(const AllocatorWithStackMemory&) = delete; |
297 | | AllocatorWithStackMemory() = default; |
298 | | ~AllocatorWithStackMemory() = default; |
299 | | |
300 | 38 | void* alloc(size_t size) { |
301 | 38 | if (size <= N) { |
302 | | if constexpr (Base::clear_memory) memset(stack_memory, 0, N); |
303 | 38 | return stack_memory; |
304 | 38 | } |
305 | | |
306 | 0 | return Base::alloc(size, Alignment); |
307 | 38 | } _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm32ELm1EE5allocEm Line | Count | Source | 300 | 26 | void* alloc(size_t size) { | 301 | 26 | if (size <= N) { | 302 | | if constexpr (Base::clear_memory) memset(stack_memory, 0, N); | 303 | 26 | return stack_memory; | 304 | 26 | } | 305 | | | 306 | 0 | return Base::alloc(size, Alignment); | 307 | 26 | } |
_ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm64ELm8EE5allocEm Line | Count | Source | 300 | 12 | void* alloc(size_t size) { | 301 | 12 | if (size <= N) { | 302 | | if constexpr (Base::clear_memory) memset(stack_memory, 0, N); | 303 | 12 | return stack_memory; | 304 | 12 | } | 305 | | | 306 | 0 | return Base::alloc(size, Alignment); | 307 | 12 | } |
|
308 | | |
309 | 30 | void free(void* buf, size_t size) { |
310 | 30 | if (size > N) Base::free(buf, size); |
311 | 30 | } _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm32ELm1EE4freeEPvm Line | Count | Source | 309 | 18 | void free(void* buf, size_t size) { | 310 | 18 | if (size > N) Base::free(buf, size); | 311 | 18 | } |
_ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm64ELm8EE4freeEPvm Line | Count | Source | 309 | 12 | void free(void* buf, size_t size) { | 310 | 12 | if (size > N) Base::free(buf, size); | 311 | 12 | } |
|
312 | | |
313 | 7 | void* realloc(void* buf, size_t old_size, size_t new_size) { |
314 | | /// Was in stack_memory, will remain there. |
315 | 7 | if (new_size <= N) return buf; |
316 | | |
317 | | /// Already was big enough to not fit in stack_memory. |
318 | 7 | if (old_size > N) return Base::realloc(buf, old_size, new_size, Alignment); |
319 | | |
320 | | /// Was in stack memory, but now will not fit there. |
321 | 7 | void* new_buf = Base::alloc(new_size, Alignment); |
322 | 7 | memcpy(new_buf, buf, old_size); |
323 | 7 | return new_buf; |
324 | 7 | } _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm32ELm1EE7reallocEPvmm Line | Count | Source | 313 | 7 | void* realloc(void* buf, size_t old_size, size_t new_size) { | 314 | | /// Was in stack_memory, will remain there. | 315 | 7 | if (new_size <= N) return buf; | 316 | | | 317 | | /// Already was big enough to not fit in stack_memory. | 318 | 7 | if (old_size > N) return Base::realloc(buf, old_size, new_size, Alignment); | 319 | | | 320 | | /// Was in stack memory, but now will not fit there. | 321 | 7 | void* new_buf = Base::alloc(new_size, Alignment); | 322 | 7 | memcpy(new_buf, buf, old_size); | 323 | 7 | return new_buf; | 324 | 7 | } |
Unexecuted instantiation: _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm64ELm8EE7reallocEPvmm |
325 | | |
326 | | bool sys_memory_exceed(size_t size, std::string* err_msg) const { |
327 | | return Base::sys_memory_exceed(size, err_msg); |
328 | | } |
329 | | |
330 | | bool memory_tracker_exceed(size_t size, std::string* err_msg) const { |
331 | | return Base::memory_tracker_exceed(size, err_msg); |
332 | | } |
333 | | |
334 | | protected: |
335 | 0 | static constexpr size_t get_stack_threshold() { return N; }Unexecuted instantiation: _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb0EEELm32ELm1EE19get_stack_thresholdEv Unexecuted instantiation: _ZN5doris24AllocatorWithStackMemoryINS_9AllocatorILb0ELb0ELb0ENS_22DefaultMemoryAllocatorELb1EEELm64ELm8EE19get_stack_thresholdEv |
336 | | }; |
337 | | } // namespace doris |