Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple cores for single ASP.net request

Tags:

c#

asp.net

iis

I am trying to create a WebApi method that runs a series of loop calculations that would be difficult to further optimize.

x.Items.AsParallel().ForAll(item =>
{
    item.RunCalcs();
});

When this code executes, by looking at the server task manager, it appears that it only maxes out a single processor core while leaving the other cores untouched.

From what I have read, asp.net limits a single request to one processor core. Since this is an intranet server with very few overall requests, I am not concerned with managing the server resources.

Is there any way to override or work around this behavior to make my loop run faster?

like image 205
phosplait Avatar asked Nov 05 '15 16:11

phosplait


1 Answers

ASP.Net can limit the number of threads used even for TPL in a very neat way. Simply by creating a TaskScheduler, which is limited to one thread and starting the ASP.Net request on given TaskScheduler. I bet, they would have a pool of these limited TaskScheuler's, it would make sense...

Then what will happen inside the task processing ASP.Net request when you call TPL or PLINQ?

It is scheduling tasks using calls to Task.Start or even better and by TPL team the more preferred way, Task.Factory.StartNew.

BUT, BUT, BUTT:), these are scheduling tasks on top of TaskScheduler.Current and that is our limited TaskScheduler we are already running on! So all the scheduled tasks will be burned on the limited TaskScheduler no matter how many cores your machine has.

On the other hand, it seems that async/await operations are using new Task.Run() introduced in .Net 4.5+ and it was suggested, that it is scheduling tasks on TashScheduler.Default, what is the ThreadPool itself, so no limitation there, other than the number of cores. I do not have proof though other than this lead: Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew() TPL

Unfortunately AsParallel() has no overload taking TaskScheduler.

So the solution would be:

  1. The first one already suggested by @S K, to use class Parallel and specify the degree of parallelism. The class predates PLINQ and is using the ThreadPool as it seems fit.
  2. The Second idea would be to schedule on ThreadPool yourself.
  3. Or schedule tasks on TaskScheduler.Default, targetting ThreadPool.
  4. Or spawn own threads(most bad idea) for ASP.Net.
  5. Or use async/await to run work on TaskScheduler.Default, the ThreadPool and in the async method use AsParalel(), because there TaskScheduler.Current would be same as TaskScheduler.Default, simply the ThreadPool.

NOTE OF CAUTION: Please note, that scheduling heavy stuff on ThreadPool in ASP.Net can lead to the decreasing performance of processing ASP.Net requests...

like image 160
ipavlu Avatar answered Sep 28 '22 00:09

ipavlu