Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET 4 Parallel.ForEach and PLINQ: can they overwhelm the thread pool and kill the app performance?

The more I use Parallel.ForEach and PLINQ in my code, the more faces and code review push backs I am getting. So I wonder is there any reason for me NOT to use PLINQ, at extreme, on each LINQ statement? Can the runtime not be smart enough to start spawning so many threads (or consuming so many threads from the thread pool) that the app performance would actually degrade instead of improve? The same question applies to Parallel library.

I do understand implications related to thread-safety and overhead of using multi-threading. I also realize not everything is good for parallelizing. All I am wondering about if I should stop defending my approaches and just give up on these two fine things because my peers think I'd better do thread control myself instead of relying on .NET facilities?

UPDATE: please assume the hardware is sufficiently good to satisfy prerequisites for use of multithreading.

like image 401
Schultz9999 Avatar asked Mar 25 '12 03:03

Schultz9999


People also ask

Is a DbContext per thread in parallel ForEach safe?

I have researched this, and I agree that DbContext is not thread-safe. The pattern I propose does use multiple threads, but a single DbContext is only every accessed by a single thread in a single-threaded fashion.

Is parallel ForEach blocking?

No, it doesn't block and returns control immediately. The items to run in parallel are done on background threads.

Why is parallel ForEach slower?

Since the work in your parallel function is very small, the overhead of the management the parallelism has to do becomes significant, thus slowing down the overall work.

Is parallel ForEach faster?

The execution of Parallel. Foreach is faster than normal ForEach.


3 Answers

It all comes down to two things:

  1. Is the extra work required to partition the collection and synchronize the threads greater than the performance gain compared to a regular foreach?

  2. Are all the threads going to use a shared resource that will become a bottle neck?

An example of the second case is doing a Parallel.ForEach over the results of a Linq to Sql statement. In that case, if your results are coming from the DB very slowly, each thread may spend more time waiting for data to process than actually doing something.

See: http://msdn.microsoft.com/en-us/library/dd997392.aspx

like image 100
Diego Avatar answered Oct 05 '22 13:10

Diego


To set the number of worker threads you can use .WithDegreeOfParallelism(N)

eg

var query = from item in source.AsParallel().WithDegreeOfParallelism(2)
            where Compute(item) > 42
            select item;

See http://msdn.microsoft.com/en-us/library/dd997425.aspx

like image 39
Not loved Avatar answered Oct 05 '22 13:10

Not loved


When dig into performance questions this deep, I think the best thing to do is... measure, measure and measure. Even if somebody answered that PLINK is great and will boost the performance of your application, would you trust that without verifing it with profiling? Although general answers may exists you cannot spare the effort to measure the performance in your exact case. The overall performance depends on so many things and it can be that PLINK helps in one case but not in the other.
My personal experiences with PLINK is that after swicthing every LINQ query into PLINK the response times are way better when the load is small, and there is no difference when the load is around its maximum. But I can imagine a case where PLINK hurts the overall performance under a huge load. Have to check it for your own particular case.
Well... and if you want to convince other people that you are walking the right path, what else would be better than measurement results?

like image 37
Hari Avatar answered Oct 05 '22 11:10

Hari