diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index 8f69b3a9672..2b1b5e32d74 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -33,6 +33,8 @@ namespace Grpc.Core public class GrpcEnvironment { const int MinDefaultThreadPoolSize = 4; + const int DefaultBatchContextPoolSharedCapacity = 10000; + const int DefaultBatchContextPoolThreadLocalCapacity = 64; static object staticLock = new object(); static GrpcEnvironment instance; @@ -40,6 +42,8 @@ namespace Grpc.Core static int? customThreadPoolSize; static int? customCompletionQueueCount; static bool inlineHandlers; + static int batchContextPoolSharedCapacity = DefaultBatchContextPoolSharedCapacity; + static int batchContextPoolThreadLocalCapacity = DefaultBatchContextPoolThreadLocalCapacity; static readonly HashSet registeredChannels = new HashSet(); static readonly HashSet registeredServers = new HashSet(); @@ -187,7 +191,7 @@ namespace Grpc.Core /// /// Sets the number of threads in the gRPC thread pool that polls for internal RPC events. - /// Can be only invoke before the GrpcEnviroment is started and cannot be changed afterwards. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. /// Setting thread pool size is an advanced setting and you should only use it if you know what you are doing. /// Most users should rely on the default value provided by gRPC library. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. @@ -204,7 +208,7 @@ namespace Grpc.Core /// /// Sets the number of completion queues in the gRPC thread pool that polls for internal RPC events. - /// Can be only invoke before the GrpcEnviroment is started and cannot be changed afterwards. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. /// Setting the number of completions queues is an advanced setting and you should only use it if you know what you are doing. /// Most users should rely on the default value provided by gRPC library. /// Note: this method is part of an experimental API that can change or be removed without any prior notice. @@ -238,6 +242,26 @@ namespace Grpc.Core } } + /// + /// Sets the parameters for a pool that caches batch context instances. Reusing batch context instances + /// instead of creating a new one for every C core operation helps reducing the GC pressure. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. + /// This is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetBatchContextPoolParams(int sharedCapacity, int threadLocalCapacity) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(sharedCapacity >= 0, "Shared capacity needs to be a non-negative number"); + GrpcPreconditions.CheckArgument(threadLocalCapacity >= 0, "Thread local capacity needs to be a non-negative number"); + batchContextPoolSharedCapacity = sharedCapacity; + batchContextPoolThreadLocalCapacity = threadLocalCapacity; + } + } + /// /// Occurs when GrpcEnvironment is about the start the shutdown logic. /// If GrpcEnvironment is later initialized and shutdown, the event will be fired again (unless unregistered first). @@ -250,8 +274,7 @@ namespace Grpc.Core private GrpcEnvironment() { GrpcNativeInit(); - // TODO(jtattermusch): configure params - batchContextPool = new DefaultObjectPool(() => BatchContextSafeHandle.Create(this.batchContextPool), 10000, 64); + batchContextPool = new DefaultObjectPool(() => BatchContextSafeHandle.Create(this.batchContextPool), batchContextPoolSharedCapacity, batchContextPoolThreadLocalCapacity); threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault(), inlineHandlers); threadPool.Start(); }