Prostakov
Prostakov

Reputation: 940

ThreadPool.SetMinThreads does not create any new threads

I am trying to figure out exactly what impact does ThreadPool.SetMinThreads makes.

According to official documentation it says

Sets the minimum number of threads the thread pool creates on demand, as new requests are made, before switching to an algorithm for managing thread creation and destruction.

In my understanding, as a developer, I'm suppose to have control over mechanism on how to spin new threads on demand, so they are created and waiting in the idle state, in situations when for example I'm expecting load of request coming at specific time.

And this is exactly what I initially thought SetMinThreads method is designed for.

But when I started actually playing with it - I got really weird results.

So I'm having my ASP.NET .NET5 application, and in controller action I'm having code like this: ThreadPool.SetMinThreads(32000, 1000);

And of course I'm intuitively expecting runtime to create 32K of worker threads and 1000 io threads for me.

And when I do that, and then call other method - Process.GetCurrentProcess().Threads to get all the process' threads, and print statistic on them, I get something like this

Standby - 17
Running - 4

I thought that maybe app needs some time to spin new threads, so I've tried diffrent delays, 1min, 5min and 10mins.

But result always stays the same, I get 15-20 Standby and 2-4 Running.

So then comes logical question - what exactly SetMinThreads method is doing at all? The description provided by MSDN does not seem very helpful.

And another logical question - what if I wanted to force dotnet to spin 32K of new threads in idle state - does dotnet provide any mechanism for it at all?

Upvotes: 6

Views: 3091

Answers (1)

Theodor Zoulias
Theodor Zoulias

Reputation: 43495

The ThreadPool.SetMinThreads sets the minimum number of threads that the ThreadPool creates instantly on demand. That's the key phrase, and it is indeed quite unintuitive. The ThreadPool currently¹ (.NET 5) works in two modes:

  1. When a new request for work arrives, and all the threads in the pool are busy, create instantly a new thread in order to satisfy the request.

  2. When a new request for work arrives, and all the threads in the pool are busy, queue the request, and wait for 1 sec before creating a new thread, hoping that in the meantime one of the worker threads will complete its current work, and will become available for serving the queued request.

The ThreadPool.SetMinThreads sets the threshold between these two modes. It does not give you control over the number of threads that are alive right now. Which is not very satisfying, but it is what it is. If you want to force the ThreadPool to create 1,000 threads instantly, you must also sent an equal number of requests for work, additionally to calling ThreadPool.SetMinThreads(1000, 1000). Something like this should do the trick:

ThreadPool.SetMinThreads(1000, 1000);
Task[] tasks = Enumerable.Range(0, 1000)
    .Select(_ => Task.Run(() => Thread.Sleep(100)))
    .ToArray();

Honestly I don't think that anyone does that. Creating a new Thread is quite fast in human time (it requires around 0.25 milliseconds per thread in my PC), so for a system that receives requests from humans, the overhead of creating a thread shouldn's have any measurable impact. On the other hand 0.25 msec is an eon in computer time, when you want a thread to do a tiny amount of work (in the range of nanoseconds), like adding something in a List<T>. That's why the ThreadPool was invented in the first place: To amortize the overhead of thread-creation for tiny but numerous workloads.

Be aware that creating a new Thread has also a memory cost, which is generally more significant than the time cost: each thread requires at least 1 MB of RAM for its stack. So creating 32,000 threads will tie down 32 GB of memory just for stack space. This is not very efficient. That's why in recent years asynchronous programming has become so prominent in server-side web development, because it allows to do more work with less threads.

¹ There is nothing preventing the Microsoft engineers from changing/twicking the implementation of the ThreadPool in the future. AFAIK this has already happened at least once in the past.

Upvotes: 9

Related Questions