-
Notifications
You must be signed in to change notification settings - Fork 606
Start MainLoop with a Task marked as LongRunning #1321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start MainLoop with a Task marked as LongRunning #1321
Conversation
Ok I found out the reason: |
Poking @stephentoub and @EgorBo here in case they have some good insights and time :) |
Hi. What kind of feedback are you looking for? |
Hi @stephentoub!
Just if this change makes sense. Seems reasonable to me but I don't have a way to reproduce the issues that @d-jagoda reports. |
Hi @stephentoub. Here is the original discussion: https://groups.google.com/g/rabbitmq-users/c/9lFwM_xF5cw The TLDR version: It is started by doing a The proposal is to use So I guess the the question is, is there a preferred alternative or an easy way to run a long-running async method on a non-ThreadPool thread? Would it work if started it using |
Is it doing blocking I/O? If it were implemented entirely asynchronously, would you still have thread starvation issues? |
I haven't tried but it would work in theory because the MainLoop start thread would eventually yield at this async IO call rabbitmq-dotnet-client/projects/RabbitMQ.Client/client/impl/Connection.Receive.cs Line 73 in 49c61dc
|
I plan on merging this later today or Monday unless someone chimes in. Seems like a good choice for |
I'm confused... is it still beneficial even when things are all async? There's a cost to spinning up a dedicated thread. |
The 6.x version has a non-async version of the MainLoop so I think it makes sense for that branch. The main branch has the async version so shouldn't be needed there. |
Thanks to everyone who contributed here. Have a great weekend! |
Proposed Changes
Addresses: #1318
.NET Core in Linux uses epoll for monitoring IO descriptors for ready states and the PortableThreadPool for dispatching events returned by epoll_wait. Unlike the Windows implementation where IO completion ports are bound to an underlying Windows thread pool the use of PortableThreadPool for async IO makes it more sensitive to long running thread pool threads as the thread pool heuristics cannot accurately determine the available threads against the demand. Quite often the Gate thread has to interfere when it detects starvation of the thread pool in order to force increase of the threads and this process can some times take a second or more.
In a containerize world, having even a single long running thread pool thread leads to reduced throughputs and timeouts on time sensitive requests whenever async IO is used - for example Kestrel.
In my tests, Marking StartMainLoop task as LongRunning has increased the throughput of our services and has gotten rid of readiness probe timeouts when deployed to Kubernetes.
Types of Changes
What types of changes does your code introduce to this project?
Put an
x
in the boxes that applyChecklist
Put an
x
in the boxes that apply. You can also fill these out after creatingthe PR. If you're unsure about any of them, don't hesitate to ask on the
mailing list. We're here to help! This is simply a reminder of what we are
going to look for before merging your code.
CONTRIBUTING.md
documentEdit: syntax of checkboxes