Open sunilnitdgp opened 6 months ago
Actually, it's normal for multiple executors to be created. The specific behaviour should be:
thread-sensitive
, there's a single shared global executor that is usedexecutor=
argument into SyncToAsync, but this is rarely done@andrewgodwin Thanks for your comment. I'm using Django as a framework, and each call is explicitly marked as thread_sensitive=True using the default ASGI handler class. For instance:
await sync_to_async(signals.request_started.send, thread_sensitive=True)(
sender=self.__class__, scope=scope
)
Considering this, ideally, a single shared global executor should be used. However, despite this setup, the code seems to be entering the else block, where a new thread executor is created in the current context instead of reusing the existing one:
if thread_sensitive_context in self.context_to_thread_executor:
# Re-use thread executor in current context
executor = self.context_to_thread_executor[thread_sensitive_context]
else:
# Create new thread executor in current context
executor = ThreadPoolExecutor(max_workers=1)
self.context_to_thread_executor[thread_sensitive_context] = executor
Since all sorts of things that you can do in your app can affect that (different middleware, server configuration, loading in something that uses gevent, etc.), we can only really debug it if you can produce a reliable way to reproduce it in a tiny sample app, unfortunately.
I understand. I'm actually working with a simple app containing just a view. Here are the steps I've followed:
python manage.py runserver
(can see the log Starting ASGI/Daphne version 4.1.0 development server at http://127.0.0.1:8000/
)top -o threads -pid <pid>
.I'm working on Mac M1 Air
Hi,
I'm attempting to run an async view using the ASGI protocol with Daphne as the server. However, I've noticed that it's creating new ThreadPoolExecutor instances for some requests, with daemon threads still running in the background post-benchmarking. My understanding is that since it's based on an event loop, it should use a single ThreadPoolExecutor. Could someone clarify this for me?
Middlewares:
And my view is:
The code I'm pointing to in sync.py