|
|
|
@ -25,10 +25,13 @@ |
|
|
|
|
#include <stdint.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
#include "absl/strings/str_cat.h" |
|
|
|
|
|
|
|
|
|
#include <grpc/slice_buffer.h> |
|
|
|
|
#include <grpc/support/alloc.h> |
|
|
|
|
#include <grpc/support/log.h> |
|
|
|
|
#include <grpc/support/string_util.h> |
|
|
|
|
|
|
|
|
|
#include "src/core/lib/gpr/useful.h" |
|
|
|
|
#include "src/core/lib/iomgr/combiner.h" |
|
|
|
@ -118,7 +121,7 @@ struct grpc_resource_user { |
|
|
|
|
grpc_resource_user_link links[GRPC_RULIST_COUNT]; |
|
|
|
|
|
|
|
|
|
/* The name of this resource user, for debugging/tracing */ |
|
|
|
|
char* name; |
|
|
|
|
std::string name; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct grpc_resource_quota { |
|
|
|
@ -181,7 +184,7 @@ struct grpc_resource_quota { |
|
|
|
|
/* Roots of all resource user lists */ |
|
|
|
|
grpc_resource_user* roots[GRPC_RULIST_COUNT]; |
|
|
|
|
|
|
|
|
|
char* name; |
|
|
|
|
std::string name; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void ru_unref_by(grpc_resource_user* resource_user, gpr_atm amount); |
|
|
|
@ -349,13 +352,13 @@ static bool rq_alloc(grpc_resource_quota* resource_quota) { |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"RQ %s %s: grant alloc %" PRId64 |
|
|
|
|
" bytes; rq_free_pool -> %" PRId64, |
|
|
|
|
resource_quota->name, resource_user->name, amt, |
|
|
|
|
resource_quota->name.c_str(), resource_user->name.c_str(), amt, |
|
|
|
|
resource_quota->free_pool); |
|
|
|
|
} |
|
|
|
|
} else if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace) && |
|
|
|
|
resource_user->free_pool >= 0) { |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: discard already satisfied alloc request", |
|
|
|
|
resource_quota->name, resource_user->name); |
|
|
|
|
resource_quota->name.c_str(), resource_user->name.c_str()); |
|
|
|
|
} |
|
|
|
|
if (resource_user->free_pool >= 0) { |
|
|
|
|
resource_user->allocating = false; |
|
|
|
@ -388,7 +391,7 @@ static bool rq_reclaim_from_per_user_free_pool( |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"RQ %s %s: reclaim_from_per_user_free_pool %" PRId64 |
|
|
|
|
" bytes; rq_free_pool -> %" PRId64, |
|
|
|
|
resource_quota->name, resource_user->name, amt, |
|
|
|
|
resource_quota->name.c_str(), resource_user->name.c_str(), amt, |
|
|
|
|
resource_quota->free_pool); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&resource_user->mu); |
|
|
|
@ -398,7 +401,7 @@ static bool rq_reclaim_from_per_user_free_pool( |
|
|
|
|
gpr_log(GPR_INFO, |
|
|
|
|
"RQ %s %s: failed to reclaim_from_per_user_free_pool; " |
|
|
|
|
"free_pool = %" PRId64 "; rq_free_pool = %" PRId64, |
|
|
|
|
resource_quota->name, resource_user->name, |
|
|
|
|
resource_quota->name.c_str(), resource_user->name.c_str(), |
|
|
|
|
resource_user->free_pool, resource_quota->free_pool); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&resource_user->mu); |
|
|
|
@ -415,8 +418,9 @@ static bool rq_reclaim(grpc_resource_quota* resource_quota, bool destructive) { |
|
|
|
|
grpc_resource_user* resource_user = rulist_pop_head(resource_quota, list); |
|
|
|
|
if (resource_user == nullptr) return false; |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: initiate %s reclamation", resource_quota->name, |
|
|
|
|
resource_user->name, destructive ? "destructive" : "benign"); |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: initiate %s reclamation", |
|
|
|
|
resource_quota->name.c_str(), resource_user->name.c_str(), |
|
|
|
|
destructive ? "destructive" : "benign"); |
|
|
|
|
} |
|
|
|
|
resource_quota->reclaiming = true; |
|
|
|
|
grpc_resource_quota_ref_internal(resource_quota); |
|
|
|
@ -585,8 +589,7 @@ static void ru_destroy(void* ru, grpc_error* /*error*/) { |
|
|
|
|
} |
|
|
|
|
grpc_resource_quota_unref_internal(resource_user->resource_quota); |
|
|
|
|
gpr_mu_destroy(&resource_user->mu); |
|
|
|
|
gpr_free(resource_user->name); |
|
|
|
|
gpr_free(resource_user); |
|
|
|
|
delete resource_user; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ru_alloc_slices( |
|
|
|
@ -640,8 +643,7 @@ static void rq_reclamation_done(void* rq, grpc_error* /*error*/) { |
|
|
|
|
|
|
|
|
|
/* Public API */ |
|
|
|
|
grpc_resource_quota* grpc_resource_quota_create(const char* name) { |
|
|
|
|
grpc_resource_quota* resource_quota = |
|
|
|
|
static_cast<grpc_resource_quota*>(gpr_malloc(sizeof(*resource_quota))); |
|
|
|
|
grpc_resource_quota* resource_quota = new grpc_resource_quota; |
|
|
|
|
gpr_ref_init(&resource_quota->refs, 1); |
|
|
|
|
resource_quota->combiner = grpc_combiner_create(); |
|
|
|
|
resource_quota->free_pool = INT64_MAX; |
|
|
|
@ -655,10 +657,10 @@ grpc_resource_quota* grpc_resource_quota_create(const char* name) { |
|
|
|
|
resource_quota->reclaiming = false; |
|
|
|
|
gpr_atm_no_barrier_store(&resource_quota->memory_usage_estimation, 0); |
|
|
|
|
if (name != nullptr) { |
|
|
|
|
resource_quota->name = gpr_strdup(name); |
|
|
|
|
resource_quota->name = name; |
|
|
|
|
} else { |
|
|
|
|
gpr_asprintf(&resource_quota->name, "anonymous_pool_%" PRIxPTR, |
|
|
|
|
(intptr_t)resource_quota); |
|
|
|
|
resource_quota->name = |
|
|
|
|
absl::StrCat("anonymous_pool_", (intptr_t)resource_quota); |
|
|
|
|
} |
|
|
|
|
GRPC_CLOSURE_INIT(&resource_quota->rq_step_closure, rq_step, resource_quota, |
|
|
|
|
nullptr); |
|
|
|
@ -675,9 +677,8 @@ void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) { |
|
|
|
|
// No outstanding thread quota
|
|
|
|
|
GPR_ASSERT(resource_quota->num_threads_allocated == 0); |
|
|
|
|
GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota"); |
|
|
|
|
gpr_free(resource_quota->name); |
|
|
|
|
gpr_mu_destroy(&resource_quota->thread_count_mu); |
|
|
|
|
gpr_free(resource_quota); |
|
|
|
|
delete resource_quota; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -774,8 +775,7 @@ const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void) { |
|
|
|
|
|
|
|
|
|
grpc_resource_user* grpc_resource_user_create( |
|
|
|
|
grpc_resource_quota* resource_quota, const char* name) { |
|
|
|
|
grpc_resource_user* resource_user = |
|
|
|
|
static_cast<grpc_resource_user*>(gpr_malloc(sizeof(*resource_user))); |
|
|
|
|
grpc_resource_user* resource_user = new grpc_resource_user; |
|
|
|
|
resource_user->resource_quota = |
|
|
|
|
grpc_resource_quota_ref_internal(resource_quota); |
|
|
|
|
GRPC_CLOSURE_INIT(&resource_user->allocate_closure, &ru_allocate, |
|
|
|
@ -805,10 +805,10 @@ grpc_resource_user* grpc_resource_user_create( |
|
|
|
|
resource_user->links[i].next = resource_user->links[i].prev = nullptr; |
|
|
|
|
} |
|
|
|
|
if (name != nullptr) { |
|
|
|
|
resource_user->name = gpr_strdup(name); |
|
|
|
|
resource_user->name = name; |
|
|
|
|
} else { |
|
|
|
|
gpr_asprintf(&resource_user->name, "anonymous_resource_user_%" PRIxPTR, |
|
|
|
|
(intptr_t)resource_user); |
|
|
|
|
resource_user->name = |
|
|
|
|
absl::StrCat("anonymous_resource_user_", (intptr_t)resource_user); |
|
|
|
|
} |
|
|
|
|
return resource_user; |
|
|
|
|
} |
|
|
|
@ -890,8 +890,8 @@ static bool resource_user_alloc_locked(grpc_resource_user* resource_user, |
|
|
|
|
resource_user->free_pool -= static_cast<int64_t>(size); |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64, |
|
|
|
|
resource_user->resource_quota->name, resource_user->name, size, |
|
|
|
|
resource_user->free_pool); |
|
|
|
|
resource_user->resource_quota->name.c_str(), |
|
|
|
|
resource_user->name.c_str(), size, resource_user->free_pool); |
|
|
|
|
} |
|
|
|
|
if (GPR_LIKELY(resource_user->free_pool >= 0)) return true; |
|
|
|
|
// Slow path: We need to wait for the free pool to refill.
|
|
|
|
@ -951,8 +951,8 @@ void grpc_resource_user_free(grpc_resource_user* resource_user, size_t size) { |
|
|
|
|
resource_user->free_pool += static_cast<int64_t>(size); |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64, |
|
|
|
|
resource_user->resource_quota->name, resource_user->name, size, |
|
|
|
|
resource_user->free_pool); |
|
|
|
|
resource_user->resource_quota->name.c_str(), |
|
|
|
|
resource_user->name.c_str(), size, resource_user->free_pool); |
|
|
|
|
} |
|
|
|
|
bool is_bigger_than_zero = resource_user->free_pool > 0; |
|
|
|
|
if (is_bigger_than_zero && was_zero_or_negative && |
|
|
|
@ -977,7 +977,8 @@ void grpc_resource_user_post_reclaimer(grpc_resource_user* resource_user, |
|
|
|
|
void grpc_resource_user_finish_reclamation(grpc_resource_user* resource_user) { |
|
|
|
|
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) { |
|
|
|
|
gpr_log(GPR_INFO, "RQ %s %s: reclamation complete", |
|
|
|
|
resource_user->resource_quota->name, resource_user->name); |
|
|
|
|
resource_user->resource_quota->name.c_str(), |
|
|
|
|
resource_user->name.c_str()); |
|
|
|
|
} |
|
|
|
|
resource_user->resource_quota->combiner->Run( |
|
|
|
|
&resource_user->resource_quota->rq_reclamation_done_closure, |
|
|
|
|