Coverage Report

Created: 2026-03-17 00:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/core/allocator.h
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