Hello all, I want to offer a quick update. tl;dr: Jeff's analysis is correct. The executor is legacy code at this point, slated for deletion, and increasingly unused.
We have been carefully replacing the legacy I/O, timer, and async execution implementations with a new public EventEngine <https://github.com/grpc/grpc/blob/63ecc4ba3ee958d8f95b133ce38dbedb70fc0658/include/grpc/event_engine/event_engine.h> API and its default implementations. The new thread pools do still auto-scale as needed - albeit with different heuristics, which are evolving as we benchmark - but threads are now reclaimed if/when gRPC calms down from a burst of activity that caused the pool to grow. Also, I believe the executor did not rate limit thread creation when closure queues reached their max depths, but the default EventEngine implementations do rate limit thread creation (currently capped at 1 new thread per second, but that's an implementation detail which may change ... some benchmarks have shown it to be a pretty effective rate). Beginning around gRPC v.148, you should see an increasing number of "event_engine" threads, and a decreasing number of executor threads. Ultimately we aim to unify all async activity into a single auto-scaling thread pool under the EventEngine. And since the EventEngine is a public API, any integrators that want complete control over thread behavior can implement their own EventEngine and plug it in to gRPC. gRPC will (eventually) use a provided engine for all async execution, timers, and I/O. Implementing an engine is not a small task, but it is an option people have been requesting for years. Otherwise, the default threading behavior provided by gRPC is tuned for performance - if starting a thread helps gRPC move faster, then that's what it will do. Hope this helps! -aj On Friday, May 12, 2023 at 4:03:58 PM UTC-7 Jiqing Tang wrote: > Thanks so much Jeff, agree reaping them after they being idle would be > great. > > On Friday, May 12, 2023 at 6:59:28 PM UTC-4 Jeff Steger wrote: > >> This is as close to an explanation as I have found: >> >> look at sreecha’s response in >> https://github.com/grpc/grpc/issues/14578 >> >> tldr: >> “ The max number of threads can be 2x >> <https://github.com/grpc/grpc/blob/v1.10.0/src/core/lib/iomgr/executor.cc#L94> >> the >> number cores and unfortunately its not configurable at the moment….. any >> executor threads and timer-manager you see are by-design; unless the >> threads are more than 2x the number of cores on your machine in which case >> it is clearly a bug” >> >> >> From my observation of the thread count and from my examination of the >> grpc code (which I admit I performed some years ago), it is evident to me >> that the grpc framework spawns threads up to 2x the number of hardware >> cores. It will spawn a new thread if an existing thread in its threadpool >> is busy iirc. The issue is that the grpc framework never reaps idle >> threads. Once a thread is created, it is there for the lifetime if the grpc >> server. There is no way to configure the max number of threads either. It >> is really imo a sloppy design. threads aren’t free and this framework keeps >> (in my case) dozens and dozens of idle threads around even during long >> periods of low or no traffic. Maybe they fixed it in newer versions, idk. >> >> On Fri, May 12, 2023 at 5:58 PM Jiqing Tang <jiqin...@gmail.com> wrote: >> >>> Hi Jeff and Mark, >>> >>> I just ran into the same issue with an async c++ GRPC server (version >>> 1.37.1), was curious about these default-executo threads and then got this >>> thread, did you guys figure out what these threads are for? The number >>> seems to be about 2x of the polling worker threads. >>> >>> Thanks! >>> >>> On Friday, January 7, 2022 at 3:47:51 PM UTC-5 Jeff Steger wrote: >>> >>>> Thanks Mark, I will turn on trace and see if I see anything odd. I was >>>> reading about a function called Executor::SetThreadingDefault(bool enable) >>>> that I think I can safely call after i create my grpc server. It is a >>>> public function and seems to allow me to toggle between a threaded >>>> implementation and an async one. Is that accurate? Is calling this >>>> function >>>> safe to do and/or recommended (or at least not contra-recommended). Thanks >>>> again for your help! >>>> >>>> Jeff >>>> >>>> >>>> >>>> On Fri, Jan 7, 2022 at 11:14 AM Mark D. Roth <ro...@google.com> wrote: >>>> >>>>> Oh, sorry, I thought you were asking about the sync server threads. >>>>> The default-executor threads sound like threads that are spawned >>>>> internally >>>>> inside of C-core for things like synchronous DNS resolution; those should >>>>> be completely unrelated to the sync server threads. I'm not sure what >>>>> would cause those threads to pile up. >>>>> >>>>> Try running with the env vars GRPC_VERBOSITY=DEBUG GRPC_TRACE=executor >>>>> and see if that yields any useful log information. In particular, try >>>>> running that with a debug build, since that will add additional >>>>> information >>>>> about where in the code the closures on the executor threads are coming >>>>> from. >>>>> >>>>> On Thu, Jan 6, 2022 at 7:05 PM Jeff Steger <be2...@gmail.com> wrote: >>>>> >>>>>> >>>>>> Thanks for the info! It sort of sounds like the default-executor >>>>>> threads and the sync-server threads come from the same thread pool. I >>>>>> know >>>>>> that ServerBuilder::SetResourceQuota sets the max number sync-server >>>>>> threads. Does it have any impact on the number of default-executor >>>>>> threads? >>>>>> It doesn't seem to. >>>>>> >>>>>> Also, can you tell me under what conditions a process can expect to >>>>>> wind up with dozens of sleeping default-executor threads? My process >>>>>> doesn't start off like that but after a few hours thats how it winds up. >>>>>> It >>>>>> is not under high load, just serving a few short-lived >>>>>> streaming-response >>>>>> queries every few seconds. If I limit the max number of these threads to >>>>>> lets say 10, do you anticipate that connections would be refused under >>>>>> these conditions (ie serving a few short-lived streaming-response >>>>>> queries >>>>>> every few seconds)? >>>>>> >>>>>> Last, is it safe to manually kill these sleeping threads? They seem >>>>>> to be blocked on a condition variable. >>>>>> >>>>>> Thanks! >>>>>> >>>>>> -Jeff >>>>>> >>>>>> On Thu, Jan 6, 2022 at 3:39 PM Mark D. Roth <ro...@google.com> wrote: >>>>>> >>>>>>> The C++ sync server has one thread pool for both polling and request >>>>>>> handlers. When a request comes in, an existing polling thread basically >>>>>>> becomes a request handler thread, and when the request handler >>>>>>> completes, >>>>>>> that thread is available to become a polling thread again. The >>>>>>> MIN_POLLERS >>>>>>> and MAX_POLLERS options >>>>>>> <https://grpc.github.io/grpc/cpp/classgrpc_1_1_server_builder.html#aff66bd93cba7d4240a64550fe1fca88d> >>>>>>> >>>>>>> (which can be set via ServerBuilder::SetSyncServerOption() >>>>>>> <https://grpc.github.io/grpc/cpp/classgrpc_1_1_server_builder.html#acbc2a859672203e7be097de55e296d4b>) >>>>>>> >>>>>>> allow tuning the number of threads that are used for polling: when a >>>>>>> polling thread becomes a request handler thread, if there are not >>>>>>> enough >>>>>>> polling threads remaining, a new one will be spawned, and when a >>>>>>> request >>>>>>> handler finishes, if there are too many polling threads, the thread >>>>>>> will >>>>>>> terminate. >>>>>>> >>>>>>> On Wed, Jan 5, 2022 at 12:54 PM Jeff Steger <be2...@gmail.com> >>>>>>> wrote: >>>>>>> >>>>>>>> Ah never mind I see you answered, apologies. Let me ask you this: >>>>>>>> am I stuck with all of these default-executor threads that my process >>>>>>>> is >>>>>>>> spawning? Is there no way to limit them? Do they come from same pool >>>>>>>> as >>>>>>>> grpc sync server threads? >>>>>>>> >>>>>>>> On Wed, Jan 5, 2022 at 3:51 PM Jeff Steger <be2...@gmail.com> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Can you specifically answer this: >>>>>>>>> >>>>>>>>> grpc-java has a method in its ServerBuilder class to set the >>>>>>>>> Executor. Is there similar functionality for grpc-c++ ? >>>>>>>>> >>>>>>>>> Thanks! >>>>>>>>> >>>>>>>>> On Tue, Jan 4, 2022 at 11:55 AM Mark D. Roth <ro...@google.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> I answered this in the other thread you posted on. >>>>>>>>>> >>>>>>>>>> On Sun, Jan 2, 2022 at 9:39 AM Jeff Steger <be2...@gmail.com> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> grpc-java has a method in its ServerBuilder class to set the >>>>>>>>>>> Executor. Is there similar functionality for grpc-c++ ? I am >>>>>>>>>>> running a C++ >>>>>>>>>>> grpc server and the number of executor threads it spawns is high >>>>>>>>>>> and seems >>>>>>>>>>> to never decrease, even when connections stop. >>>>>>>>>>> >>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>> Google Groups "grpc.io" group. >>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>> it, send an email to grpc-io+u...@googlegroups.com. >>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>> https://groups.google.com/d/msgid/grpc-io/CAA-WHunWvX5Tr6Vp3e-E6vcKgzD%3DGzsCNoZzqNNQ8Ox8BZvggA%40mail.gmail.com >>>>>>>>>>> >>>>>>>>>>> <https://groups.google.com/d/msgid/grpc-io/CAA-WHunWvX5Tr6Vp3e-E6vcKgzD%3DGzsCNoZzqNNQ8Ox8BZvggA%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>>>>>> . >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Mark D. Roth <ro...@google.com> >>>>>>>>>> Software Engineer >>>>>>>>>> Google, Inc. >>>>>>>>>> >>>>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Mark D. Roth <ro...@google.com> >>>>>>> Software Engineer >>>>>>> Google, Inc. >>>>>>> >>>>>> >>>>> >>>>> -- >>>>> Mark D. Roth <ro...@google.com> >>>>> Software Engineer >>>>> Google, Inc. >>>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "grpc.io" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to grpc-io+u...@googlegroups.com. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/grpc-io/3ef87e52-f06e-492f-aecd-b6a58b3bd654n%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/grpc-io/3ef87e52-f06e-492f-aecd-b6a58b3bd654n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- You received this message because you are subscribed to the Google Groups "grpc.io" group. To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/d6eb990c-30bc-464d-a8f1-72fc64350b23n%40googlegroups.com.