memory_quota.cc
Go to the documentation of this file.
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
18 
19 #include <inttypes.h>
20 
21 #include <algorithm>
22 #include <atomic>
23 #include <tuple>
24 #include <type_traits>
25 
26 #include "absl/status/status.h"
27 #include "absl/strings/str_cat.h"
28 #include "absl/utility/utility.h"
29 
39 
40 namespace grpc_core {
41 
42 // Maximum number of bytes an allocator will request from a quota in one step.
43 // Larger allocations than this will require multiple allocation requests.
44 static constexpr size_t kMaxReplenishBytes = 1024 * 1024;
45 
46 // Minimum number of bytes an allocator will request from a quota in one step.
47 static constexpr size_t kMinReplenishBytes = 4096;
48 
49 //
50 // Reclaimer
51 //
52 
54  if (memory_quota_ != nullptr) {
55  memory_quota_->FinishReclamation(sweep_token_, std::move(waker_));
56  }
57 }
58 
59 //
60 // ReclaimerQueue
61 //
62 
68 };
69 
72  MultiProducerSingleConsumerQueue queue; // reader_mu must be held to pop
74 
75  ~State() {
76  bool empty = false;
77  do {
78  delete static_cast<QueuedNode*>(queue.PopAndCheckEnd(&empty));
79  } while (!empty);
80  }
81 };
82 
84  if (auto* sweep = sweep_.exchange(nullptr, std::memory_order_acq_rel)) {
85  sweep->RunAndDelete(absl::nullopt);
86  }
87  Unref();
88 }
89 
91  if (auto* sweep = sweep_.exchange(nullptr, std::memory_order_acq_rel)) {
92  sweep->RunAndDelete(std::move(reclamation_sweep));
93  }
94 }
95 
97  if (sweep_.load(std::memory_order_relaxed)) {
98  new_queue->Enqueue(Ref());
99  return true;
100  } else {
101  return false;
102  }
103 }
104 
106  // When we cancel a reclaimer we rotate the elements of the queue once -
107  // taking one non-cancelled node from the start, and placing it on the end.
108  // This ensures that we don't suffer from head of line blocking whereby a
109  // non-cancelled reclaimer at the head of the queue, in the absence of memory
110  // pressure, prevents the remainder of the queue from being cleaned up.
111  MutexLock lock(&state_->reader_mu);
112  while (true) {
113  bool empty = false;
114  std::unique_ptr<QueuedNode> node(
115  static_cast<QueuedNode*>(state_->queue.PopAndCheckEnd(&empty)));
116  if (node == nullptr) break;
117  if (node->reclaimer_handle->sweep_.load(std::memory_order_relaxed) !=
118  nullptr) {
119  state_->queue.Push(node.release());
120  break;
121  }
122  }
123 }
124 
126 
128 
130  if (state_->queue.Push(new QueuedNode(std::move(handle)))) {
131  MutexLock lock(&state_->reader_mu);
132  state_->waker.Wakeup();
133  }
134 }
135 
137  MutexLock lock(&state_->reader_mu);
138  bool empty = false;
139  // Try to pull from the queue.
140  std::unique_ptr<QueuedNode> node(
141  static_cast<QueuedNode*>(state_->queue.PopAndCheckEnd(&empty)));
142  // If we get something, great.
143  if (node != nullptr) return std::move(node->reclaimer_handle);
144  if (!empty) {
145  // If we don't, but the queue is probably not empty, schedule an immediate
146  // repoll.
148  } else {
149  // Otherwise, schedule a wakeup for whenever something is pushed.
151  }
152  return Pending{};
153 }
154 
155 //
156 // GrpcMemoryAllocatorImpl
157 //
158 
160  std::shared_ptr<BasicMemoryQuota> memory_quota, std::string name)
161  : memory_quota_(memory_quota), name_(std::move(name)) {
163 }
164 
166  GPR_ASSERT(free_bytes_.load(std::memory_order_acquire) +
167  sizeof(GrpcMemoryAllocatorImpl) ==
168  taken_bytes_.load(std::memory_order_relaxed));
169  memory_quota_->Return(taken_bytes_);
170 }
171 
173  std::shared_ptr<BasicMemoryQuota> memory_quota;
175  reclamation_handles[kNumReclamationPasses];
176  {
177  MutexLock lock(&reclaimer_mu_);
179  shutdown_ = true;
180  memory_quota = memory_quota_;
181  for (size_t i = 0; i < kNumReclamationPasses; i++) {
182  reclamation_handles[i] = absl::exchange(reclamation_handles_[i], nullptr);
183  }
184  }
185 }
186 
188  // Validate request - performed here so we don't bloat the generated code with
189  // inlined asserts.
190  GPR_ASSERT(request.min() <= request.max());
192  while (true) {
193  // Attempt to reserve memory from our pool.
194  auto reservation = TryReserve(request);
195  if (reservation.has_value()) {
196  return *reservation;
197  }
198  // If that failed, grab more from the quota and retry.
199  Replenish();
200  }
201 }
202 
205  // How much memory should we request? (see the scaling below)
206  size_t scaled_size_over_min = request.max() - request.min();
207  // Scale the request down according to memory pressure if we have that
208  // flexibility.
209  if (scaled_size_over_min != 0) {
210  const auto pressure_and_max_recommended_allocation_size =
211  memory_quota_->InstantaneousPressureAndMaxRecommendedAllocationSize();
212  double pressure = pressure_and_max_recommended_allocation_size.first;
213  size_t max_recommended_allocation_size =
214  pressure_and_max_recommended_allocation_size.second;
215  // Reduce allocation size proportional to the pressure > 80% usage.
216  if (pressure > 0.8) {
217  scaled_size_over_min =
218  std::min(scaled_size_over_min,
219  static_cast<size_t>((request.max() - request.min()) *
220  (1.0 - pressure) / 0.2));
221  }
222  if (max_recommended_allocation_size < request.min()) {
223  scaled_size_over_min = 0;
224  } else if (request.min() + scaled_size_over_min >
225  max_recommended_allocation_size) {
226  scaled_size_over_min = max_recommended_allocation_size - request.min();
227  }
228  }
229 
230  // How much do we want to reserve?
231  const size_t reserve = request.min() + scaled_size_over_min;
232  // See how many bytes are available.
233  size_t available = free_bytes_.load(std::memory_order_acquire);
234  while (true) {
235  // Does the current free pool satisfy the request?
236  if (available < reserve) {
237  return {};
238  }
239  // Try to reserve the requested amount.
240  // If the amount of free memory changed through this loop, then available
241  // will be set to the new value and we'll repeat.
242  if (free_bytes_.compare_exchange_weak(available, available - reserve,
243  std::memory_order_acq_rel,
244  std::memory_order_acquire)) {
245  return reserve;
246  }
247  }
248 }
249 
251  size_t free = free_bytes_.load(std::memory_order_relaxed);
252  const size_t kReduceToSize = kMaxQuotaBufferSize / 2;
253  while (true) {
254  if (free <= kReduceToSize) return;
255  size_t ret = free - kReduceToSize;
256  if (free_bytes_.compare_exchange_weak(free, kReduceToSize,
257  std::memory_order_acq_rel,
258  std::memory_order_acquire)) {
260  gpr_log(GPR_INFO, "[%p|%s] Early return %" PRIdPTR " bytes", this,
261  name_.c_str(), ret);
262  }
263  GPR_ASSERT(taken_bytes_.fetch_sub(ret, std::memory_order_relaxed) >= ret);
264  memory_quota_->Return(ret);
265  return;
266  }
267  }
268 }
269 
271  // Attempt a fairly low rate exponential growth request size, bounded between
272  // some reasonable limits declared at top of file.
273  auto amount = Clamp(taken_bytes_.load(std::memory_order_relaxed) / 3,
275  // Take the requested amount from the quota.
276  memory_quota_->Take(amount);
277  // Record that we've taken it.
278  taken_bytes_.fetch_add(amount, std::memory_order_relaxed);
279  // Add the taken amount to the free pool.
280  free_bytes_.fetch_add(amount, std::memory_order_acq_rel);
281  // See if we can add ourselves as a reclaimer.
283 }
284 
286  // If the reclaimer is already registered, then there's nothing to do.
287  if (registered_reclaimer_.exchange(true, std::memory_order_relaxed)) {
288  return;
289  }
290  MutexLock lock(&reclaimer_mu_);
291  if (shutdown_) return;
292  // Grab references to the things we'll need
293  auto self = shared_from_this();
294  std::weak_ptr<EventEngineMemoryAllocatorImpl> self_weak{self};
295  registered_reclaimer_ = true;
296  InsertReclaimer(0, [self_weak](absl::optional<ReclamationSweep> sweep) {
297  if (!sweep.has_value()) return;
298  auto self = self_weak.lock();
299  if (self == nullptr) return;
300  auto* p = static_cast<GrpcMemoryAllocatorImpl*>(self.get());
301  p->registered_reclaimer_.store(false, std::memory_order_relaxed);
302  // Figure out how many bytes we can return to the quota.
303  size_t return_bytes = p->free_bytes_.exchange(0, std::memory_order_acq_rel);
304  if (return_bytes == 0) return;
305  // Subtract that from our outstanding balance.
306  p->taken_bytes_.fetch_sub(return_bytes);
307  // And return them to the quota.
308  p->memory_quota_->Return(return_bytes);
309  });
310 }
311 
312 //
313 // BasicMemoryQuota
314 //
315 
317  public:
318  WaitForSweepPromise(std::shared_ptr<BasicMemoryQuota> memory_quota,
319  uint64_t token)
320  : memory_quota_(std::move(memory_quota)), token_(token) {}
321 
322  struct Empty {};
324  if (memory_quota_->reclamation_counter_.load(std::memory_order_relaxed) !=
325  token_) {
326  return Empty{};
327  } else {
328  return Pending{};
329  }
330  }
331 
332  private:
333  std::shared_ptr<BasicMemoryQuota> memory_quota_;
335 };
336 
338  auto self = shared_from_this();
339 
340  // Reclamation loop:
341  // basically, wait until we are in overcommit (free_bytes_ < 0), and then:
342  // while (free_bytes_ < 0) reclaim_memory()
343  // ... and repeat
344  auto reclamation_loop = Loop(Seq(
345  [self]() -> Poll<int> {
346  // If there's free memory we no longer need to reclaim memory!
347  if (self->free_bytes_.load(std::memory_order_acquire) > 0) {
348  return Pending{};
349  }
350  return 0;
351  },
352  [self]() {
353  // Race biases to the first thing that completes... so this will
354  // choose the highest priority/least destructive thing to do that's
355  // available.
356  auto annotate = [](const char* name) {
358  return std::make_tuple(name, std::move(f));
359  };
360  };
361  return Race(Map(self->reclaimers_[0].Next(), annotate("compact")),
362  Map(self->reclaimers_[1].Next(), annotate("benign")),
363  Map(self->reclaimers_[2].Next(), annotate("idle")),
364  Map(self->reclaimers_[3].Next(), annotate("destructive")));
365  },
366  [self](
367  std::tuple<const char*, RefCountedPtr<ReclaimerQueue::Handle>> arg) {
368  auto reclaimer = std::move(std::get<1>(arg));
370  double free = std::max(intptr_t(0), self->free_bytes_.load());
371  size_t quota_size = self->quota_size_.load();
373  "RQ: %s perform %s reclamation. Available free bytes: %f, "
374  "total quota_size: %zu",
375  self->name_.c_str(), std::get<0>(arg), free, quota_size);
376  }
377  // One of the reclaimer queues gave us a way to get back memory.
378  // Call the reclaimer with a token that contains enough to wake us
379  // up again.
380  const uint64_t token =
381  self->reclamation_counter_.fetch_add(1, std::memory_order_relaxed) +
382  1;
383  reclaimer->Run(ReclamationSweep(
384  self, token, Activity::current()->MakeNonOwningWaker()));
385  // Return a promise that will wait for our barrier. This will be
386  // awoken by the token above being destroyed. So, once that token is
387  // destroyed, we'll be able to proceed.
388  return WaitForSweepPromise(self, token);
389  },
390  []() -> LoopCtl<absl::Status> {
391  // Continue the loop!
392  return Continue{};
393  }));
394 
395  reclaimer_activity_ =
396  MakeActivity(std::move(reclamation_loop), ExecCtxWakeupScheduler(),
397  [](absl::Status status) {
399  });
400 }
401 
402 void BasicMemoryQuota::Stop() { reclaimer_activity_.reset(); }
403 
404 void BasicMemoryQuota::SetSize(size_t new_size) {
405  size_t old_size = quota_size_.exchange(new_size, std::memory_order_relaxed);
406  if (old_size < new_size) {
407  // We're growing the quota.
409  } else {
410  // We're shrinking the quota.
411  Take(old_size - new_size);
412  }
413 }
414 
415 void BasicMemoryQuota::Take(size_t amount) {
416  // If there's a request for nothing, then do nothing!
417  if (amount == 0) return;
419  // Grab memory from the quota.
420  auto prior = free_bytes_.fetch_sub(amount, std::memory_order_acq_rel);
421  // If we push into overcommit, awake the reclaimer.
422  if (prior >= 0 && prior < static_cast<intptr_t>(amount)) {
423  if (reclaimer_activity_ != nullptr) reclaimer_activity_->ForceWakeup();
424  }
425 }
426 
427 void BasicMemoryQuota::FinishReclamation(uint64_t token, Waker waker) {
428  uint64_t current = reclamation_counter_.load(std::memory_order_relaxed);
429  if (current != token) return;
430  if (reclamation_counter_.compare_exchange_strong(current, current + 1,
431  std::memory_order_relaxed,
432  std::memory_order_relaxed)) {
434  double free = std::max(intptr_t(0), free_bytes_.load());
435  size_t quota_size = quota_size_.load();
437  "RQ: %s reclamation complete. Available free bytes: %f, "
438  "total quota_size: %zu",
439  name_.c_str(), free, quota_size);
440  }
441  waker.Wakeup();
442  }
443 }
444 
445 void BasicMemoryQuota::Return(size_t amount) {
446  free_bytes_.fetch_add(amount, std::memory_order_relaxed);
447 }
448 
449 std::pair<double, size_t>
450 BasicMemoryQuota::InstantaneousPressureAndMaxRecommendedAllocationSize() const {
451  double free = free_bytes_.load();
452  if (free < 0) free = 0;
453  size_t quota_size = quota_size_.load();
454  double size = quota_size;
455  if (size < 1) return std::make_pair(1.0, 1);
456  double pressure = (size - free) / size;
457  if (pressure < 0.0) pressure = 0.0;
458  if (pressure > 1.0) pressure = 1.0;
459  return std::make_pair(pressure, quota_size / 16);
460 }
461 
462 //
463 // MemoryQuota
464 //
465 
466 MemoryAllocator MemoryQuota::CreateMemoryAllocator(absl::string_view name) {
467  auto impl = std::make_shared<GrpcMemoryAllocatorImpl>(
468  memory_quota_, absl::StrCat(memory_quota_->name(), "/allocator/", name));
469  return MemoryAllocator(std::move(impl));
470 }
471 
472 MemoryOwner MemoryQuota::CreateMemoryOwner(absl::string_view name) {
473  auto impl = std::make_shared<GrpcMemoryAllocatorImpl>(
474  memory_quota_, absl::StrCat(memory_quota_->name(), "/owner/", name));
475  return MemoryOwner(std::move(impl));
476 }
477 
478 } // namespace grpc_core
trace.h
grpc_core::MemoryOwner
Definition: memory_quota.h:381
grpc_core::BasicMemoryQuota::WaitForSweepPromise::WaitForSweepPromise
WaitForSweepPromise(std::shared_ptr< BasicMemoryQuota > memory_quota, uint64_t token)
Definition: memory_quota.cc:318
grpc_core::Activity::MakeNonOwningWaker
virtual Waker MakeNonOwningWaker()=0
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
grpc_core::BasicMemoryQuota::Start
void Start()
Definition: memory_quota.cc:337
mpscq.h
grpc_core::ReclaimerQueue::State::reader_mu
Mutex reader_mu
Definition: memory_quota.cc:71
grpc_core::ReclaimerQueue::state_
std::shared_ptr< State > state_
Definition: memory_quota.h:220
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
reserve
static bool reserve(upb_pb_encoder *e, size_t bytes)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:7630
grpc_event_engine::experimental::MemoryAllocator
Definition: memory_allocator.h:35
GPR_DEBUG_ASSERT
#define GPR_DEBUG_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:103
grpc_event_engine::experimental::MemoryRequest::max_allowed_size
static constexpr size_t max_allowed_size()
Maximum allowable request size - hard coded to 1GB.
Definition: memory_request.h:38
std::tr1::make_tuple
tuple make_tuple()
Definition: cares/cares/test/gmock-1.8.0/gtest/gtest.h:1619
testing::Return
internal::ReturnAction< R > Return(R value)
Definition: bloaty/third_party/googletest/googlemock/include/gmock/gmock-actions.h:1004
grpc_core::InternallyRefCounted< Handle >::Unref
void Unref()
Definition: orphanable.h:100
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::Activity::current
static Activity * current()
Definition: activity.h:124
grpc_core::MutexLock
Definition: src/core/lib/gprpp/sync.h:88
benchmark.request
request
Definition: benchmark.py:77
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
useful.h
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
grpc_core::GrpcMemoryAllocatorImpl::MaybeDonateBack
void MaybeDonateBack()
Definition: memory_quota.cc:250
binary_size.new_size
def new_size
Definition: binary_size.py:124
grpc_core::GrpcMemoryAllocatorImpl
Definition: memory_quota.h:285
grpc_core::MultiProducerSingleConsumerQueue
Definition: mpscq.h:35
status
absl::Status status
Definition: rls.cc:251
setup.name
name
Definition: setup.py:542
grpc_resource_quota_trace
grpc_core::TraceFlag grpc_resource_quota_trace(false, "resource_quota")
name_
const std::string name_
Definition: priority.cc:233
grpc_core::ReclamationSweep::~ReclamationSweep
~ReclamationSweep()
Definition: memory_quota.cc:53
seq.h
GRPC_TRACE_FLAG_ENABLED
#define GRPC_TRACE_FLAG_ENABLED(f)
Definition: debug/trace.h:114
grpc_core::kMinReplenishBytes
static constexpr size_t kMinReplenishBytes
Definition: memory_quota.cc:47
grpc_core::ReclamationSweep::waker_
Waker waker_
Definition: memory_quota.h:120
grpc_core::ReclaimerQueue::State
Definition: memory_quota.cc:70
grpc_core::BasicMemoryQuota::WaitForSweepPromise::memory_quota_
std::shared_ptr< BasicMemoryQuota > memory_quota_
Definition: memory_quota.cc:333
grpc_core::BasicMemoryQuota::WaitForSweepPromise::Empty
Definition: memory_quota.cc:322
grpc_core::MakeActivity
ActivityPtr MakeActivity(Factory promise_factory, WakeupScheduler wakeup_scheduler, OnDone on_done, Contexts &&... contexts)
Definition: activity.h:522
map.h
grpc_core::GrpcMemoryAllocatorImpl::MaybeRegisterReclaimer
void MaybeRegisterReclaimer() ABSL_LOCKS_EXCLUDED(reclaimer_mu_)
Definition: memory_quota.cc:285
grpc_core::Race
promise_detail::Race< Promises... > Race(Promises... promises)
Definition: race.h:77
grpc_core::GrpcMemoryAllocatorImpl::reclaimer_mu_
Mutex reclaimer_mu_
Definition: memory_quota.h:362
grpc_core::Pending
Definition: poll.h:29
exec_ctx_wakeup_scheduler.h
grpc_core::ReclaimerQueue::QueuedNode
Definition: memory_quota.cc:63
grpc_core::RefCountedPtr
Definition: ref_counted_ptr.h:35
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
grpc_core::ReclaimerQueue::State::queue
MultiProducerSingleConsumerQueue queue
Definition: memory_quota.cc:72
grpc_core::GrpcMemoryAllocatorImpl::Shutdown
void Shutdown() override
Definition: memory_quota.cc:172
queue
Definition: sync_test.cc:39
grpc_core::ReclaimerQueue::Handle::Run
void Run(ReclamationSweep reclamation_sweep)
Definition: memory_quota.cc:90
absl::optional::has_value
constexpr bool has_value() const noexcept
Definition: abseil-cpp/absl/types/optional.h:461
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
grpc_core::ReclamationSweep::memory_quota_
std::shared_ptr< BasicMemoryQuota > memory_quota_
Definition: memory_quota.h:118
grpc_core::GrpcMemoryAllocatorImpl::Reserve
size_t Reserve(MemoryRequest request) override
Definition: memory_quota.cc:187
grpc_core::GrpcMemoryAllocatorImpl::memory_quota_
const std::shared_ptr< BasicMemoryQuota > memory_quota_
Definition: memory_quota.h:353
grpc_core::ReclaimerQueue
Definition: memory_quota.h:123
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::optional< size_t >
grpc_core::ReclaimerQueue::~ReclaimerQueue
~ReclaimerQueue()
arg
Definition: cmdline.cc:40
grpc_core::GrpcMemoryAllocatorImpl::GrpcMemoryAllocatorImpl
GrpcMemoryAllocatorImpl(std::shared_ptr< BasicMemoryQuota > memory_quota, std::string name)
Definition: memory_quota.cc:159
intptr_t
_W64 signed int intptr_t
Definition: stdint-msvc2008.h:118
grpc_core::BasicMemoryQuota::WaitForSweepPromise::operator()
Poll< Empty > operator()()
Definition: memory_quota.cc:323
trace.h
grpc_core::ReclaimerQueue::ReclaimerQueue
ReclaimerQueue()
Definition: memory_quota.cc:125
min
#define min(a, b)
Definition: qsort.h:83
memory_quota_
MemoryQuotaRefPtr memory_quota_
Definition: chttp2_server.cc:282
grpc_core::ReclaimerQueue::State::~State
~State()
Definition: memory_quota.cc:75
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
grpc_core::GrpcMemoryAllocatorImpl::Replenish
void Replenish()
Definition: memory_quota.cc:270
grpc_core::ReclamationSweep
Definition: memory_quota.h:88
grpc_core::ReclamationSweep::sweep_token_
uint64_t sweep_token_
Definition: memory_quota.h:119
race.h
grpc_core::Loop
promise_detail::Loop< F > Loop(F f)
Definition: loop.h:130
grpc_core::ReclaimerQueue::State::ABSL_GUARDED_BY
Waker waker ABSL_GUARDED_BY(reader_mu)
grpc_core::GrpcMemoryAllocatorImpl::free_bytes_
std::atomic< size_t > free_bytes_
Definition: memory_quota.h:358
grpc_core::Mutex
Definition: src/core/lib/gprpp/sync.h:61
shutdown_
bool shutdown_
Definition: pick_first.cc:173
absl::StatusCode::kCancelled
@ kCancelled
grpc_core::Clamp
T Clamp(T val, T min, T max)
Definition: useful.h:31
grpc_core::GrpcMemoryAllocatorImpl::registered_reclaimer_
std::atomic< bool > registered_reclaimer_
Definition: memory_quota.h:361
grpc_core::GrpcMemoryAllocatorImpl::taken_bytes_
std::atomic< size_t > taken_bytes_
Definition: memory_quota.h:360
grpc_core::ReclaimerQueue::Enqueue
void Enqueue(RefCountedPtr< Handle > handle)
Definition: memory_quota.cc:129
grpc_core::Waker
Definition: activity.h:61
grpc_core::GrpcMemoryAllocatorImpl::TryReserve
absl::optional< size_t > TryReserve(MemoryRequest request) GRPC_MUST_USE_RESULT
Definition: memory_quota.cc:203
grpc_core::ReclaimerQueue::QueuedNode::QueuedNode
QueuedNode(RefCountedPtr< Handle > reclaimer_handle)
Definition: memory_quota.cc:65
absl::Status
Definition: third_party/abseil-cpp/absl/status/status.h:424
loop.h
grpc_core::ReclaimerQueue::PollNext
Poll< RefCountedPtr< Handle > > PollNext()
Definition: memory_quota.cc:136
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
grpc_core::OrphanablePtr
std::unique_ptr< T, Deleter > OrphanablePtr
Definition: orphanable.h:64
grpc_core::MultiProducerSingleConsumerQueue::Node
Definition: mpscq.h:38
grpc_core::Activity::ForceImmediateRepoll
virtual void ForceImmediateRepoll()=0
grpc_core::ReclaimerQueue::Handle::Sweep::MarkCancelled
void MarkCancelled()
Definition: memory_quota.cc:105
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
grpc_core::BasicMemoryQuota::WaitForSweepPromise
Definition: memory_quota.cc:316
arg
struct arg arg
memory_quota.h
grpc_core::kNumReclamationPasses
static constexpr size_t kNumReclamationPasses
Definition: memory_quota.h:82
grpc_core::ReclaimerQueue::Handle::Orphan
void Orphan() final
Definition: memory_quota.cc:83
grpc_core::ReclaimerQueue::Handle::Requeue
bool Requeue(ReclaimerQueue *new_queue)
Definition: memory_quota.cc:96
grpc_core::Map
promise_detail::Map< Promise, Fn > Map(Promise promise, Fn fn)
Definition: src/core/lib/promise/map.h:67
grpc_core::ReclaimerQueue::QueuedNode::reclaimer_handle
RefCountedPtr< Handle > reclaimer_handle
Definition: memory_quota.cc:67
handle
static csh handle
Definition: test_arm_regression.c:16
grpc_core::Waker::Wakeup
void Wakeup()
Definition: activity.h:77
grpc_core::Seq
promise_detail::Seq< Functors... > Seq(Functors... functors)
Definition: seq.h:62
grpc_core::GrpcMemoryAllocatorImpl::InsertReclaimer
void InsertReclaimer(size_t pass, F fn) ABSL_EXCLUSIVE_LOCKS_REQUIRED(reclaimer_mu_)
Definition: memory_quota.h:346
grpc_core::GrpcMemoryAllocatorImpl::name_
std::string name_
Definition: memory_quota.h:370
grpc_core::BasicMemoryQuota::WaitForSweepPromise::token_
uint64_t token_
Definition: memory_quota.cc:334
grpc_core::kMaxReplenishBytes
static constexpr size_t kMaxReplenishBytes
Definition: memory_quota.cc:44
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
self
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern self
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/map.c:543
testing::Ref
internal::RefMatcher< T & > Ref(T &x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8628
absl::Status::code
absl::StatusCode code() const
Definition: third_party/abseil-cpp/absl/status/status.cc:233
absl::variant
Definition: abseil-cpp/absl/types/internal/variant.h:46
grpc_core::GrpcMemoryAllocatorImpl::~GrpcMemoryAllocatorImpl
~GrpcMemoryAllocatorImpl() override
Definition: memory_quota.cc:165
grpc_core::ReclaimerQueue::Handle::sweep_
std::atomic< Sweep * > sweep_
Definition: memory_quota.h:178
grpc_event_engine::experimental::MemoryRequest
Reservation request - how much memory do we want to allocate?
Definition: memory_request.h:27
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
binary_size.old_size
old_size
Definition: binary_size.py:125
grpc_core::kMaxQuotaBufferSize
static constexpr size_t kMaxQuotaBufferSize
Definition: memory_quota.h:83
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
absl::exchange
T exchange(T &obj, U &&new_value)
Definition: abseil-cpp/absl/utility/utility.h:314
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:23