/Users/deen/code/yugabyte-db/src/yb/util/memory/arena.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2010 Google Inc. All Rights Reserved |
2 | | // |
3 | | // Licensed to the Apache Software Foundation (ASF) under one |
4 | | // or more contributor license agreements. See the NOTICE file |
5 | | // distributed with this work for additional information |
6 | | // regarding copyright ownership. The ASF licenses this file |
7 | | // to you under the Apache License, Version 2.0 (the |
8 | | // "License"); you may not use this file except in compliance |
9 | | // with the License. You may obtain a copy of the License at |
10 | | // |
11 | | // http://www.apache.org/licenses/LICENSE-2.0 |
12 | | // |
13 | | // Unless required by applicable law or agreed to in writing, |
14 | | // software distributed under the License is distributed on an |
15 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
16 | | // KIND, either express or implied. See the License for the |
17 | | // specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // The following only applies to changes made to this file as part of YugaByte development. |
21 | | // |
22 | | // Portions Copyright (c) YugaByte, Inc. |
23 | | // |
24 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
25 | | // in compliance with the License. You may obtain a copy of the License at |
26 | | // |
27 | | // http://www.apache.org/licenses/LICENSE-2.0 |
28 | | // |
29 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
30 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
31 | | // or implied. See the License for the specific language governing permissions and limitations |
32 | | // under the License. |
33 | | // |
34 | | |
35 | | #include "yb/util/memory/arena.h" |
36 | | |
37 | | #include <algorithm> |
38 | | #include <mutex> |
39 | | |
40 | | #include "yb/util/alignment.h" |
41 | | #include "yb/util/debug-util.h" |
42 | | #include "yb/util/flag_tags.h" |
43 | | |
44 | | using std::copy; |
45 | | using std::max; |
46 | | using std::min; |
47 | | using std::reverse; |
48 | | using std::shared_ptr; |
49 | | using std::sort; |
50 | | using std::swap; |
51 | | |
52 | | DEFINE_uint64(arena_warn_threshold_bytes, 256*1024*1024, |
53 | | "Number of bytes beyond which to emit a warning for a large arena"); |
54 | | TAG_FLAG(arena_warn_threshold_bytes, hidden); |
55 | | |
56 | | namespace yb { |
57 | | namespace internal { |
58 | | |
59 | | template <class Traits> |
60 | 81.5M | uint8_t* ArenaComponent<Traits>::AllocateBytesAligned(const size_t size, const size_t alignment) { |
61 | | // Special case check the allowed alignments. Currently, we only ensure |
62 | | // the allocated buffer components are 16-byte aligned, and the code path |
63 | | // doesn't support larger alignment. |
64 | 20.8k | DCHECK(alignment == 1 || alignment == 2 || alignment == 4 || |
65 | 20.8k | alignment == 8 || alignment == 16) |
66 | 20.8k | << "bad alignment: " << alignment; |
67 | | |
68 | 81.5M | for (;;) { |
69 | 81.5M | uint8_t* position = position_; |
70 | | |
71 | 81.5M | const auto aligned = align_up(position, alignment); |
72 | 81.5M | const auto new_position = aligned + size; |
73 | | |
74 | 81.5M | if (PREDICT_TRUE(new_position <= end_)) { |
75 | 80.7M | bool success = Traits::CompareExchange(new_position, &position_, &position); |
76 | 80.7M | if (PREDICT_TRUE(success)) { |
77 | 80.7M | AsanUnpoison(aligned, size); |
78 | 80.7M | return aligned; |
79 | 80.7M | } |
80 | 854k | } else { |
81 | 854k | return nullptr; |
82 | 854k | } |
83 | 81.5M | } |
84 | 81.5M | } _ZN2yb8internal14ArenaComponentINS0_21ThreadSafeArenaTraitsEE20AllocateBytesAlignedEmm Line | Count | Source | 60 | 51.7M | uint8_t* ArenaComponent<Traits>::AllocateBytesAligned(const size_t size, const size_t alignment) { | 61 | | // Special case check the allowed alignments. Currently, we only ensure | 62 | | // the allocated buffer components are 16-byte aligned, and the code path | 63 | | // doesn't support larger alignment. | 64 | 12.2k | DCHECK(alignment == 1 || alignment == 2 || alignment == 4 || | 65 | 12.2k | alignment == 8 || alignment == 16) | 66 | 12.2k | << "bad alignment: " << alignment; | 67 | | | 68 | 51.9M | for (;;) { | 69 | 51.9M | uint8_t* position = position_; | 70 | | | 71 | 51.9M | const auto aligned = align_up(position, alignment); | 72 | 51.9M | const auto new_position = aligned + size; | 73 | | | 74 | 51.9M | if (PREDICT_TRUE(new_position <= end_)) { | 75 | 51.8M | bool success = Traits::CompareExchange(new_position, &position_, &position); | 76 | 51.9M | if (PREDICT_TRUE(success)) { | 77 | 51.9M | AsanUnpoison(aligned, size); | 78 | 51.9M | return aligned; | 79 | 51.9M | } | 80 | 59.6k | } else { | 81 | 59.6k | return nullptr; | 82 | 59.6k | } | 83 | 51.9M | } | 84 | 51.7M | } |
_ZN2yb8internal14ArenaComponentINS0_11ArenaTraitsEE20AllocateBytesAlignedEmm Line | Count | Source | 60 | 29.7M | uint8_t* ArenaComponent<Traits>::AllocateBytesAligned(const size_t size, const size_t alignment) { | 61 | | // Special case check the allowed alignments. Currently, we only ensure | 62 | | // the allocated buffer components are 16-byte aligned, and the code path | 63 | | // doesn't support larger alignment. | 64 | 8.60k | DCHECK(alignment == 1 || alignment == 2 || alignment == 4 || | 65 | 8.60k | alignment == 8 || alignment == 16) | 66 | 8.60k | << "bad alignment: " << alignment; | 67 | | | 68 | 29.6M | for (;;) { | 69 | 29.6M | uint8_t* position = position_; | 70 | | | 71 | 29.6M | const auto aligned = align_up(position, alignment); | 72 | 29.6M | const auto new_position = aligned + size; | 73 | | | 74 | 29.6M | if (PREDICT_TRUE(new_position <= end_)) { | 75 | 28.8M | bool success = Traits::CompareExchange(new_position, &position_, &position); | 76 | 28.8M | if (PREDICT_TRUE(success)) { | 77 | 28.8M | AsanUnpoison(aligned, size); | 78 | 28.8M | return aligned; | 79 | 28.8M | } | 80 | 795k | } else { | 81 | 795k | return nullptr; | 82 | 795k | } | 83 | 29.6M | } | 84 | 29.7M | } |
|
85 | | |
86 | | template <class Traits> |
87 | 92.6M | inline void ArenaComponent<Traits>::AsanUnpoison(const void* addr, size_t size) { |
88 | | #ifdef ADDRESS_SANITIZER |
89 | | std::lock_guard<mutex_type> l(asan_lock_); |
90 | | ASAN_UNPOISON_MEMORY_REGION(addr, size); |
91 | | #endif |
92 | 92.6M | } _ZN2yb8internal14ArenaComponentINS0_21ThreadSafeArenaTraitsEE12AsanUnpoisonEPKvm Line | Count | Source | 87 | 62.2M | inline void ArenaComponent<Traits>::AsanUnpoison(const void* addr, size_t size) { | 88 | | #ifdef ADDRESS_SANITIZER | 89 | | std::lock_guard<mutex_type> l(asan_lock_); | 90 | | ASAN_UNPOISON_MEMORY_REGION(addr, size); | 91 | | #endif | 92 | 62.2M | } |
_ZN2yb8internal14ArenaComponentINS0_11ArenaTraitsEE12AsanUnpoisonEPKvm Line | Count | Source | 87 | 30.3M | inline void ArenaComponent<Traits>::AsanUnpoison(const void* addr, size_t size) { | 88 | | #ifdef ADDRESS_SANITIZER | 89 | | std::lock_guard<mutex_type> l(asan_lock_); | 90 | | ASAN_UNPOISON_MEMORY_REGION(addr, size); | 91 | | #endif | 92 | 30.3M | } |
|
93 | | |
94 | | // Fast-path allocation should get inlined, and fall-back |
95 | | // to non-inline function call for allocation failure |
96 | | template <class Traits> |
97 | 80.6M | inline void *ArenaBase<Traits>::AllocateBytesAligned(const size_t size, const size_t align) { |
98 | 80.6M | void* result = AcquireLoadCurrent()->AllocateBytesAligned(size, align); |
99 | 80.6M | if (PREDICT_TRUE(result != nullptr)) return result; |
100 | 275k | return AllocateBytesFallback(size, align); |
101 | 275k | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE20AllocateBytesAlignedEmm Line | Count | Source | 97 | 51.7M | inline void *ArenaBase<Traits>::AllocateBytesAligned(const size_t size, const size_t align) { | 98 | 51.7M | void* result = AcquireLoadCurrent()->AllocateBytesAligned(size, align); | 99 | 51.9M | if (PREDICT_TRUE(result != nullptr)) return result; | 100 | 18.4E | return AllocateBytesFallback(size, align); | 101 | 18.4E | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE20AllocateBytesAlignedEmm Line | Count | Source | 97 | 28.9M | inline void *ArenaBase<Traits>::AllocateBytesAligned(const size_t size, const size_t align) { | 98 | 28.9M | void* result = AcquireLoadCurrent()->AllocateBytesAligned(size, align); | 99 | 28.9M | if (PREDICT_TRUE(result != nullptr)) return result; | 100 | 466k | return AllocateBytesFallback(size, align); | 101 | 466k | } |
|
102 | | |
103 | | template <class Traits> |
104 | 473 | inline uint8_t* ArenaBase<Traits>::AddSlice(const Slice& value) { |
105 | 473 | return reinterpret_cast<uint8_t *>(AddBytes(value.data(), value.size())); |
106 | 473 | } Unexecuted instantiation: _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE8AddSliceERKNS_5SliceE _ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE8AddSliceERKNS_5SliceE Line | Count | Source | 104 | 473 | inline uint8_t* ArenaBase<Traits>::AddSlice(const Slice& value) { | 105 | 473 | return reinterpret_cast<uint8_t *>(AddBytes(value.data(), value.size())); | 106 | 473 | } |
|
107 | | |
108 | | template <class Traits> |
109 | 473 | inline void *ArenaBase<Traits>::AddBytes(const void *data, size_t len) { |
110 | 473 | void* destination = AllocateBytes(len); |
111 | 473 | if (destination == nullptr) return nullptr; |
112 | 473 | memcpy(destination, data, len); |
113 | 473 | return destination; |
114 | 473 | } Unexecuted instantiation: _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE8AddBytesEPKvm _ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE8AddBytesEPKvm Line | Count | Source | 109 | 473 | inline void *ArenaBase<Traits>::AddBytes(const void *data, size_t len) { | 110 | 473 | void* destination = AllocateBytes(len); | 111 | 473 | if (destination == nullptr) return nullptr; | 112 | 473 | memcpy(destination, data, len); | 113 | 473 | return destination; | 114 | 473 | } |
|
115 | | |
116 | | template <class Traits> |
117 | 9 | inline bool ArenaBase<Traits>::RelocateSlice(const Slice &src, Slice *dst) { |
118 | 9 | void* destination = AllocateBytes(src.size()); |
119 | 9 | if (destination == nullptr) return false; |
120 | 9 | memcpy(destination, src.data(), src.size()); |
121 | 9 | *dst = Slice(reinterpret_cast<uint8_t *>(destination), src.size()); |
122 | 9 | return true; |
123 | 9 | } Unexecuted instantiation: _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE13RelocateSliceERKNS_5SliceEPS4_ _ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE13RelocateSliceERKNS_5SliceEPS4_ Line | Count | Source | 117 | 9 | inline bool ArenaBase<Traits>::RelocateSlice(const Slice &src, Slice *dst) { | 118 | 9 | void* destination = AllocateBytes(src.size()); | 119 | 9 | if (destination == nullptr) return false; | 120 | 9 | memcpy(destination, src.data(), src.size()); | 121 | 9 | *dst = Slice(reinterpret_cast<uint8_t *>(destination), src.size()); | 122 | 9 | return true; | 123 | 9 | } |
|
124 | | |
125 | | template <class Traits> |
126 | | ArenaBase<Traits>::ArenaBase( |
127 | | BufferAllocator* const buffer_allocator, |
128 | | size_t initial_buffer_size, |
129 | | size_t max_buffer_size) |
130 | | : buffer_allocator_(buffer_allocator), |
131 | 671k | max_buffer_size_(max_buffer_size) { |
132 | 671k | AddComponentUnlocked(NewBuffer(initial_buffer_size, 0)); |
133 | 671k | } Unexecuted instantiation: _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEEC2EPNS_15BufferAllocatorEmm _ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEEC2EPNS_15BufferAllocatorEmm Line | Count | Source | 131 | 671k | max_buffer_size_(max_buffer_size) { | 132 | 671k | AddComponentUnlocked(NewBuffer(initial_buffer_size, 0)); | 133 | 671k | } |
|
134 | | |
135 | | template <class Traits> |
136 | | ArenaBase<Traits>::ArenaBase(size_t initial_buffer_size, size_t max_buffer_size) |
137 | | : buffer_allocator_(HeapBufferAllocator::Get()), |
138 | 2.71M | max_buffer_size_(max_buffer_size) { |
139 | 2.71M | AddComponentUnlocked(NewBuffer(initial_buffer_size, 0)); |
140 | 2.71M | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEEC2Emm Line | Count | Source | 138 | 2.27M | max_buffer_size_(max_buffer_size) { | 139 | 2.27M | AddComponentUnlocked(NewBuffer(initial_buffer_size, 0)); | 140 | 2.27M | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEEC2Emm Line | Count | Source | 138 | 438k | max_buffer_size_(max_buffer_size) { | 139 | 438k | AddComponentUnlocked(NewBuffer(initial_buffer_size, 0)); | 140 | 438k | } |
|
141 | | |
142 | | template <class Traits> |
143 | 3.21M | ArenaBase<Traits>::~ArenaBase() { |
144 | 3.21M | AcquireLoadCurrent()->Destroy(buffer_allocator_); |
145 | 3.21M | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEED2Ev Line | Count | Source | 143 | 2.10M | ArenaBase<Traits>::~ArenaBase() { | 144 | 2.10M | AcquireLoadCurrent()->Destroy(buffer_allocator_); | 145 | 2.10M | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEED2Ev Line | Count | Source | 143 | 1.11M | ArenaBase<Traits>::~ArenaBase() { | 144 | 1.11M | AcquireLoadCurrent()->Destroy(buffer_allocator_); | 145 | 1.11M | } |
|
146 | | |
147 | | template <class Traits> |
148 | 393k | void *ArenaBase<Traits>::AllocateBytesFallback(const size_t size, const size_t align) { |
149 | 393k | std::lock_guard<mutex_type> lock(component_lock_); |
150 | | |
151 | | // It's possible another thread raced with us and already allocated |
152 | | // a new component, in which case we should try the "fast path" again |
153 | 393k | Component* cur = CHECK_NOTNULL(AcquireLoadCurrent()); |
154 | 393k | void * result = cur->AllocateBytesAligned(size, align); |
155 | 393k | if (PREDICT_FALSE(result != nullptr)) return result; |
156 | | |
157 | | // Really need to allocate more space. |
158 | 391k | const size_t buffer_size = size + sizeof(Component); |
159 | | // But, allocate enough, even if the request is large. In this case, |
160 | | // might violate the max_element_size bound. |
161 | 391k | size_t next_component_size = std::max(std::min(2 * cur->full_size(), max_buffer_size_), |
162 | 391k | buffer_size); |
163 | | |
164 | | // If soft quota is exhausted we will only get the "minimal" amount of memory |
165 | | // we ask for. In this case if we always use "size" as minimal, we may degrade |
166 | | // to allocating a lot of tiny components, one for each string added to the |
167 | | // arena. This would be very inefficient, so let's first try something between |
168 | | // "size" and "next_component_size". If it fails due to hard quota being |
169 | | // exhausted, we'll fall back to using "size" as minimal. |
170 | 391k | size_t minimal = (buffer_size + next_component_size) / 2; |
171 | 391k | CHECK_LE(buffer_size, minimal); |
172 | 391k | CHECK_LE(minimal, next_component_size); |
173 | | // Now, just make sure we can actually get the memory. |
174 | 391k | Buffer buffer = NewBufferInTwoAttempts(next_component_size, minimal, buffer_size); |
175 | 391k | if (!buffer) return nullptr; |
176 | | |
177 | | // Now, must succeed. The component has at least 'size' bytes. |
178 | 391k | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); |
179 | 391k | auto component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); |
180 | 391k | result = component->AllocateBytesAligned(size, align); |
181 | 391k | CHECK(result != nullptr); |
182 | | |
183 | | // Now add it to the arena. |
184 | 391k | AddComponentUnlocked(std::move(buffer), component); |
185 | | |
186 | 391k | return result; |
187 | 391k | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE21AllocateBytesFallbackEmm Line | Count | Source | 148 | 2.61k | void *ArenaBase<Traits>::AllocateBytesFallback(const size_t size, const size_t align) { | 149 | 2.61k | std::lock_guard<mutex_type> lock(component_lock_); | 150 | | | 151 | | // It's possible another thread raced with us and already allocated | 152 | | // a new component, in which case we should try the "fast path" again | 153 | 2.61k | Component* cur = CHECK_NOTNULL(AcquireLoadCurrent()); | 154 | 2.61k | void * result = cur->AllocateBytesAligned(size, align); | 155 | 2.61k | if (PREDICT_FALSE(result != nullptr)) return result; | 156 | | | 157 | | // Really need to allocate more space. | 158 | 199 | const size_t buffer_size = size + sizeof(Component); | 159 | | // But, allocate enough, even if the request is large. In this case, | 160 | | // might violate the max_element_size bound. | 161 | 199 | size_t next_component_size = std::max(std::min(2 * cur->full_size(), max_buffer_size_), | 162 | 199 | buffer_size); | 163 | | | 164 | | // If soft quota is exhausted we will only get the "minimal" amount of memory | 165 | | // we ask for. In this case if we always use "size" as minimal, we may degrade | 166 | | // to allocating a lot of tiny components, one for each string added to the | 167 | | // arena. This would be very inefficient, so let's first try something between | 168 | | // "size" and "next_component_size". If it fails due to hard quota being | 169 | | // exhausted, we'll fall back to using "size" as minimal. | 170 | 199 | size_t minimal = (buffer_size + next_component_size) / 2; | 171 | 199 | CHECK_LE(buffer_size, minimal); | 172 | 199 | CHECK_LE(minimal, next_component_size); | 173 | | // Now, just make sure we can actually get the memory. | 174 | 199 | Buffer buffer = NewBufferInTwoAttempts(next_component_size, minimal, buffer_size); | 175 | 199 | if (!buffer) return nullptr; | 176 | | | 177 | | // Now, must succeed. The component has at least 'size' bytes. | 178 | 199 | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); | 179 | 199 | auto component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); | 180 | 199 | result = component->AllocateBytesAligned(size, align); | 181 | 199 | CHECK(result != nullptr); | 182 | | | 183 | | // Now add it to the arena. | 184 | 199 | AddComponentUnlocked(std::move(buffer), component); | 185 | | | 186 | 199 | return result; | 187 | 199 | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE21AllocateBytesFallbackEmm Line | Count | Source | 148 | 391k | void *ArenaBase<Traits>::AllocateBytesFallback(const size_t size, const size_t align) { | 149 | 391k | std::lock_guard<mutex_type> lock(component_lock_); | 150 | | | 151 | | // It's possible another thread raced with us and already allocated | 152 | | // a new component, in which case we should try the "fast path" again | 153 | 391k | Component* cur = CHECK_NOTNULL(AcquireLoadCurrent()); | 154 | 391k | void * result = cur->AllocateBytesAligned(size, align); | 155 | 391k | if (PREDICT_FALSE(result != nullptr)) return result; | 156 | | | 157 | | // Really need to allocate more space. | 158 | 391k | const size_t buffer_size = size + sizeof(Component); | 159 | | // But, allocate enough, even if the request is large. In this case, | 160 | | // might violate the max_element_size bound. | 161 | 391k | size_t next_component_size = std::max(std::min(2 * cur->full_size(), max_buffer_size_), | 162 | 391k | buffer_size); | 163 | | | 164 | | // If soft quota is exhausted we will only get the "minimal" amount of memory | 165 | | // we ask for. In this case if we always use "size" as minimal, we may degrade | 166 | | // to allocating a lot of tiny components, one for each string added to the | 167 | | // arena. This would be very inefficient, so let's first try something between | 168 | | // "size" and "next_component_size". If it fails due to hard quota being | 169 | | // exhausted, we'll fall back to using "size" as minimal. | 170 | 391k | size_t minimal = (buffer_size + next_component_size) / 2; | 171 | 391k | CHECK_LE(buffer_size, minimal); | 172 | 391k | CHECK_LE(minimal, next_component_size); | 173 | | // Now, just make sure we can actually get the memory. | 174 | 391k | Buffer buffer = NewBufferInTwoAttempts(next_component_size, minimal, buffer_size); | 175 | 391k | if (!buffer) return nullptr; | 176 | | | 177 | | // Now, must succeed. The component has at least 'size' bytes. | 178 | 391k | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); | 179 | 391k | auto component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); | 180 | 391k | result = component->AllocateBytesAligned(size, align); | 181 | 391k | CHECK(result != nullptr); | 182 | | | 183 | | // Now add it to the arena. | 184 | 391k | AddComponentUnlocked(std::move(buffer), component); | 185 | | | 186 | 391k | return result; | 187 | 391k | } |
|
188 | | |
189 | | template <class Traits> |
190 | | Buffer ArenaBase<Traits>::NewBufferInTwoAttempts(size_t requested_size, |
191 | | size_t mid_size, |
192 | 392k | size_t min_size) { |
193 | 392k | Buffer buffer = NewBuffer(requested_size, mid_size); |
194 | 392k | if (!buffer) { |
195 | 1 | return NewBuffer(requested_size, min_size); |
196 | 1 | } |
197 | 392k | return buffer; |
198 | 392k | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE22NewBufferInTwoAttemptsEmmm Line | Count | Source | 192 | 1.86k | size_t min_size) { | 193 | 1.86k | Buffer buffer = NewBuffer(requested_size, mid_size); | 194 | 1.86k | if (!buffer) { | 195 | 0 | return NewBuffer(requested_size, min_size); | 196 | 0 | } | 197 | 1.86k | return buffer; | 198 | 1.86k | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE22NewBufferInTwoAttemptsEmmm Line | Count | Source | 192 | 390k | size_t min_size) { | 193 | 390k | Buffer buffer = NewBuffer(requested_size, mid_size); | 194 | 390k | if (!buffer) { | 195 | 1 | return NewBuffer(requested_size, min_size); | 196 | 1 | } | 197 | 390k | return buffer; | 198 | 390k | } |
|
199 | | |
200 | | template <class Traits> |
201 | 12.0M | Buffer ArenaBase<Traits>::NewBuffer(size_t requested_size, size_t minimum_size) { |
202 | 12.0M | const size_t min_possible = sizeof(Component) * 2; |
203 | 12.0M | requested_size = std::max(requested_size, min_possible); |
204 | 12.0M | minimum_size = std::max(minimum_size, min_possible); |
205 | 12.0M | Buffer buffer = buffer_allocator_->BestEffortAllocate(requested_size, minimum_size); |
206 | 12.0M | if (!buffer) |
207 | 2 | return buffer; |
208 | | |
209 | 0 | CHECK_EQ(reinterpret_cast<uintptr_t>(buffer.data()) & (16 - 1), 0) |
210 | 0 | << "Components should be 16-byte aligned: " << buffer.data(); |
211 | | |
212 | 12.0M | ASAN_POISON_MEMORY_REGION(buffer.data(), buffer.size()); |
213 | | |
214 | 12.0M | return buffer; |
215 | 12.0M | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE9NewBufferEmm Line | Count | Source | 201 | 10.5M | Buffer ArenaBase<Traits>::NewBuffer(size_t requested_size, size_t minimum_size) { | 202 | 10.5M | const size_t min_possible = sizeof(Component) * 2; | 203 | 10.5M | requested_size = std::max(requested_size, min_possible); | 204 | 10.5M | minimum_size = std::max(minimum_size, min_possible); | 205 | 10.5M | Buffer buffer = buffer_allocator_->BestEffortAllocate(requested_size, minimum_size); | 206 | 10.5M | if (!buffer) | 207 | 0 | return buffer; | 208 | | | 209 | 0 | CHECK_EQ(reinterpret_cast<uintptr_t>(buffer.data()) & (16 - 1), 0) | 210 | 0 | << "Components should be 16-byte aligned: " << buffer.data(); | 211 | | | 212 | 10.5M | ASAN_POISON_MEMORY_REGION(buffer.data(), buffer.size()); | 213 | | | 214 | 10.5M | return buffer; | 215 | 10.5M | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE9NewBufferEmm Line | Count | Source | 201 | 1.50M | Buffer ArenaBase<Traits>::NewBuffer(size_t requested_size, size_t minimum_size) { | 202 | 1.50M | const size_t min_possible = sizeof(Component) * 2; | 203 | 1.50M | requested_size = std::max(requested_size, min_possible); | 204 | 1.50M | minimum_size = std::max(minimum_size, min_possible); | 205 | 1.50M | Buffer buffer = buffer_allocator_->BestEffortAllocate(requested_size, minimum_size); | 206 | 1.50M | if (!buffer) | 207 | 2 | return buffer; | 208 | | | 209 | 0 | CHECK_EQ(reinterpret_cast<uintptr_t>(buffer.data()) & (16 - 1), 0) | 210 | 0 | << "Components should be 16-byte aligned: " << buffer.data(); | 211 | | | 212 | 1.50M | ASAN_POISON_MEMORY_REGION(buffer.data(), buffer.size()); | 213 | | | 214 | 1.50M | return buffer; | 215 | 1.50M | } |
|
216 | | |
217 | | // LOCKING: component_lock_ must be held by the current thread. |
218 | | template <class Traits> |
219 | 12.0M | void ArenaBase<Traits>::AddComponentUnlocked(Buffer buffer, Component* component) { |
220 | 12.0M | if (!component) { |
221 | 11.6M | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); |
222 | 11.6M | component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); |
223 | 11.6M | } |
224 | | |
225 | 12.0M | buffer.Release(); |
226 | 12.0M | ReleaseStoreCurrent(component); |
227 | 12.0M | arena_footprint_ += component->full_size(); |
228 | 12.0M | if (PREDICT_FALSE(arena_footprint_ > FLAGS_arena_warn_threshold_bytes) && !warned_) { |
229 | 0 | LOG(WARNING) << "Arena " << reinterpret_cast<const void *>(this) |
230 | 0 | << " footprint (" << arena_footprint_ << " bytes) exceeded warning threshold (" |
231 | 0 | << FLAGS_arena_warn_threshold_bytes << " bytes)\n" |
232 | 0 | << GetStackTrace(); |
233 | 0 | warned_ = true; |
234 | 0 | } |
235 | 12.0M | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE20AddComponentUnlockedENS_6BufferEPNS0_14ArenaComponentIS2_EE Line | Count | Source | 219 | 10.5M | void ArenaBase<Traits>::AddComponentUnlocked(Buffer buffer, Component* component) { | 220 | 10.5M | if (!component) { | 221 | 10.5M | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); | 222 | 10.5M | component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); | 223 | 10.5M | } | 224 | | | 225 | 10.5M | buffer.Release(); | 226 | 10.5M | ReleaseStoreCurrent(component); | 227 | 10.5M | arena_footprint_ += component->full_size(); | 228 | 10.5M | if (PREDICT_FALSE(arena_footprint_ > FLAGS_arena_warn_threshold_bytes) && !warned_) { | 229 | 0 | LOG(WARNING) << "Arena " << reinterpret_cast<const void *>(this) | 230 | 0 | << " footprint (" << arena_footprint_ << " bytes) exceeded warning threshold (" | 231 | 0 | << FLAGS_arena_warn_threshold_bytes << " bytes)\n" | 232 | 0 | << GetStackTrace(); | 233 | 0 | warned_ = true; | 234 | 0 | } | 235 | 10.5M | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE20AddComponentUnlockedENS_6BufferEPNS0_14ArenaComponentIS2_EE Line | Count | Source | 219 | 1.50M | void ArenaBase<Traits>::AddComponentUnlocked(Buffer buffer, Component* component) { | 220 | 1.50M | if (!component) { | 221 | 1.11M | ASAN_UNPOISON_MEMORY_REGION(buffer.data(), sizeof(Component)); | 222 | 1.11M | component = new (buffer.data()) Component(buffer.size(), AcquireLoadCurrent()); | 223 | 1.11M | } | 224 | | | 225 | 1.50M | buffer.Release(); | 226 | 1.50M | ReleaseStoreCurrent(component); | 227 | 1.50M | arena_footprint_ += component->full_size(); | 228 | 1.50M | if (PREDICT_FALSE(arena_footprint_ > FLAGS_arena_warn_threshold_bytes) && !warned_) { | 229 | 0 | LOG(WARNING) << "Arena " << reinterpret_cast<const void *>(this) | 230 | 0 | << " footprint (" << arena_footprint_ << " bytes) exceeded warning threshold (" | 231 | 0 | << FLAGS_arena_warn_threshold_bytes << " bytes)\n" | 232 | 0 | << GetStackTrace(); | 233 | 0 | warned_ = true; | 234 | 0 | } | 235 | 1.50M | } |
|
236 | | |
237 | | template <class Traits> |
238 | 8.30M | void ArenaBase<Traits>::Reset() { |
239 | 8.30M | std::lock_guard<mutex_type> lock(component_lock_); |
240 | | |
241 | 8.30M | auto* current = CHECK_NOTNULL(AcquireLoadCurrent()); |
242 | 8.30M | current->Reset(buffer_allocator_); |
243 | 8.30M | arena_footprint_ = current->full_size(); |
244 | 8.30M | warned_ = false; |
245 | | |
246 | 8.30M | #ifndef NDEBUG |
247 | | // In debug mode release the last component too for (hopefully) better |
248 | | // detection of memory-related bugs (invalid shallow copies, etc.). |
249 | 8.30M | size_t last_size = current->full_size(); |
250 | 8.30M | current->Destroy(buffer_allocator_); |
251 | 8.30M | arena_footprint_ = 0; |
252 | 8.30M | ReleaseStoreCurrent(nullptr); |
253 | 8.30M | AddComponentUnlocked(NewBuffer(last_size, 0)); |
254 | 8.30M | #endif |
255 | 8.30M | } _ZN2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE5ResetEv Line | Count | Source | 238 | 8.30M | void ArenaBase<Traits>::Reset() { | 239 | 8.30M | std::lock_guard<mutex_type> lock(component_lock_); | 240 | | | 241 | 8.30M | auto* current = CHECK_NOTNULL(AcquireLoadCurrent()); | 242 | 8.30M | current->Reset(buffer_allocator_); | 243 | 8.30M | arena_footprint_ = current->full_size(); | 244 | 8.30M | warned_ = false; | 245 | | | 246 | 8.30M | #ifndef NDEBUG | 247 | | // In debug mode release the last component too for (hopefully) better | 248 | | // detection of memory-related bugs (invalid shallow copies, etc.). | 249 | 8.30M | size_t last_size = current->full_size(); | 250 | 8.30M | current->Destroy(buffer_allocator_); | 251 | 8.30M | arena_footprint_ = 0; | 252 | 8.30M | ReleaseStoreCurrent(nullptr); | 253 | 8.30M | AddComponentUnlocked(NewBuffer(last_size, 0)); | 254 | 8.30M | #endif | 255 | 8.30M | } |
_ZN2yb8internal9ArenaBaseINS0_11ArenaTraitsEE5ResetEv Line | Count | Source | 238 | 3 | void ArenaBase<Traits>::Reset() { | 239 | 3 | std::lock_guard<mutex_type> lock(component_lock_); | 240 | | | 241 | 3 | auto* current = CHECK_NOTNULL(AcquireLoadCurrent()); | 242 | 3 | current->Reset(buffer_allocator_); | 243 | 3 | arena_footprint_ = current->full_size(); | 244 | 3 | warned_ = false; | 245 | | | 246 | 3 | #ifndef NDEBUG | 247 | | // In debug mode release the last component too for (hopefully) better | 248 | | // detection of memory-related bugs (invalid shallow copies, etc.). | 249 | 3 | size_t last_size = current->full_size(); | 250 | 3 | current->Destroy(buffer_allocator_); | 251 | 3 | arena_footprint_ = 0; | 252 | 3 | ReleaseStoreCurrent(nullptr); | 253 | 3 | AddComponentUnlocked(NewBuffer(last_size, 0)); | 254 | 3 | #endif | 255 | 3 | } |
|
256 | | |
257 | | template <class Traits> |
258 | 6.07M | size_t ArenaBase<Traits>::memory_footprint() const { |
259 | 6.07M | std::lock_guard<mutex_type> lock(component_lock_); |
260 | 6.07M | return arena_footprint_; |
261 | 6.07M | } _ZNK2yb8internal9ArenaBaseINS0_21ThreadSafeArenaTraitsEE16memory_footprintEv Line | Count | Source | 258 | 6.07M | size_t ArenaBase<Traits>::memory_footprint() const { | 259 | 6.07M | std::lock_guard<mutex_type> lock(component_lock_); | 260 | 6.07M | return arena_footprint_; | 261 | 6.07M | } |
Unexecuted instantiation: _ZNK2yb8internal9ArenaBaseINS0_11ArenaTraitsEE16memory_footprintEv |
262 | | |
263 | | // Explicit instantiation. |
264 | | template class ArenaBase<ThreadSafeArenaTraits>; |
265 | | template class ArenaBase<ArenaTraits>; |
266 | | |
267 | | } // namespace internal |
268 | | } // namespace yb |