diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index da488034ca9..036a26b7ec0 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -67,6 +67,9 @@ #define MAX_SEND_EXTRA_METADATA_COUNT 3 +// Used to create arena for the first call. +#define ESTIMATED_MDELEM_COUNT 16 + /* Status data for a request can come from several sources; this enumerates them all, and acts as a priority sorting for which status to return to the application - earlier entries override @@ -323,6 +326,11 @@ static parent_call* get_parent_call(grpc_call* call) { return (parent_call*)gpr_atm_acq_load(&call->parent_call_atm); } +size_t grpc_call_get_initial_size_estimate() { + return sizeof(grpc_call) + sizeof(batch_control) * MAX_CONCURRENT_BATCHES + + sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT; +} + grpc_error* grpc_call_create(const grpc_call_create_args* args, grpc_call** out_call) { GPR_TIMER_SCOPE("grpc_call_create", 0); @@ -1144,9 +1152,9 @@ static int batch_slot_for_op(grpc_op_type type) { GPR_UNREACHABLE_CODE(return 123456789); } -static batch_control* allocate_batch_control(grpc_call* call, - const grpc_op* ops, - size_t num_ops) { +static batch_control* reuse_or_allocate_batch_control(grpc_call* call, + const grpc_op* ops, + size_t num_ops) { int slot = batch_slot_for_op(ops[0].op); batch_control** pslot = &call->active_batches[slot]; if (*pslot == nullptr) { @@ -1565,7 +1573,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, goto done; } - bctl = allocate_batch_control(call, ops, nops); + bctl = reuse_or_allocate_batch_control(call, ops, nops); if (bctl == nullptr) { return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; } diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 793cce4efa9..e000f13e7d3 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -98,6 +98,11 @@ void* grpc_call_context_get(grpc_call* call, grpc_context_index elem); uint8_t grpc_call_is_client(grpc_call* call); +/* Get the estimated memory size for a call BESIDES the call stack. Combined + * with the size of the call stack, it helps estimate the arena size for the + * initial call. */ +size_t grpc_call_get_initial_size_estimate(); + /* Return an appropriate compression algorithm for the requested compression \a * level in the context of \a call. */ grpc_compression_algorithm grpc_call_compression_for_level( diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index d740ebd4114..10bc5900a16 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -112,7 +112,8 @@ grpc_channel* grpc_channel_create_with_builder( gpr_atm_no_barrier_store( &channel->call_size_estimate, - (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size); + (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size + + grpc_call_get_initial_size_estimate()); grpc_compression_options_init(&channel->compression_options); for (size_t i = 0; i < args->num_args; i++) {