In general, the way to achieve performance in Python is to use a
single thread, not multiple threads. This is because of the
global interpreter lock. When a thread is accessing Python objects, no other thread in the process may access any objects. A god lock for all of Python. As a result, threads in Python will buy
concurrency but not
parallelism. What's more, the cost of inter-thread synchronization results in thread-based concurrency being less performant than single-thread concurrency. As a result, the assumption for asyncio is that you use a
single thread except for compatibility/interop reasons.
This may change in the future depending on the fate of
PEP 703, but the core CPython development team is currently hyper-focused on
single threaded performance, not multi-threaded performance. If and when the core Python development team changes their stance on this, we'll reassess, but for the moment, if you're looking to performantly run gRPC Python, you should do it with asyncio on a single thread.