YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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