问题描述:

I'm having a List<Boss> Collection, every Boss has 2 to 10 Assistant Staff. I'm grouping all the Employees including Boss. Now I'm having List<Person>, from this I'm searching "Raj" using Parallel LINQ, where can I place the supportive method AsParallel() to get better performance, Before or After the Where Clause ?

public class Person

{

public int EmpID { get; set; }

public string Name { get; set; }

public string Department { get; set; }

public string Gender { get; set; }

}

void Main()

{

List<Boss> BossList = new List<Boss>()

{

new Boss()

{

EmpID = 101,

Name = "Harry",

Department = "Development",

Gender = "Male",

Employees = new List<Person>()

{

new Person() {EmpID = 102, Name = "Peter", Department = "Development",Gender = "Male"},

new Person() {EmpID = 103, Name = "Emma Watson", Department = "Development",Gender = "Female"},

}

},

new Boss()

{

EmpID = 104,

Name = "Raj",

Department = "Development",

Gender = "Male",

Employees = new List<Person>()

{

new Person() {EmpID = 105, Name = "Kaliya", Department = "Development",Gender = "Male"},

new Person() {EmpID = 103, Name = "Emma Watson", Department = "Development",Gender = "Female"},

}

}

};

List<Person> result = BossList

.SelectMany(x =>

new[] { new Person { Name = x.Name, Department = x.Department, Gender = x.Gender, EmpID = x.EmpID } }

.Concat(x.Employees))

.GroupBy(x => x.EmpID) //Group by employee ID

.Select(g => g.First()) //And select a single instance for each unique employee

.ToList();

List<Person> SelectedResult = new List<Person>();

// AsParallel() - Before Where Clause

SelectedResult = result.AsParallel().Where(m => m.Name.ToLowerInvariant().Contains("Raj".ToLowerInvariant())).ToList();

// AsParallel() - After Where Clause

SelectedResult = result.Where(m => m.Name.ToLowerInvariant().Contains("Raj".ToLowerInvariant())).AsParallel().ToList();

}

Core Source Code:

 List<Person> SelectedResult = new List<Person>();

// AsParallel() - Before Where Clause

SelectedResult = result.AsParallel().Where(m => m.Name.ToLowerInvariant().Contains("Raj".ToLowerInvariant())).ToList();

// AsParallel() - After Where Clause

SelectedResult = result.Where(m => m.Name.ToLowerInvariant().Contains("Raj".ToLowerInvariant())).AsParallel().ToList();

网友答案:

Before.

AsParallel helps us to run queries in parallel, which is enabling parallel threads to improve performance. If you put before WHERE clause the filtering will be done in series, and only then will anything be parallelized.

Here is some test code:

using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;

class AsParallelTest
{
    static void Main()
    {
        var query = Enumerable.Range(0, 1000)
                              .Select(ProjectionExample)
                              .Where(x => x > 10)
                              .AsParallel();

        Stopwatch stopWatch = Stopwatch.StartNew();
        int count = query.Count();
        stopWatch.Stop();

        Console.WriteLine("Count: {0} in {1}ms", count,
                          stopWatch.ElapsedMilliseconds);

        query = Enumerable.Range(0, 1000)
                          .AsParallel()
                          .Select(ProjectionExample)
                          .Where(x => x > 10);

        stopWatch = Stopwatch.StartNew();
        count = query.Count();
        stopWatch.Stop();

        Console.WriteLine("Count: {0} in {1}ms", count,
                       stopWatch.ElapsedMilliseconds);
   }

   static int ProjectionExample(int arg)
   {
       Thread.Sleep(10);
       return arg;
   }
}

Result:

Count: 989 in 10574ms
Count: 989 in 1409ms

It's obvious that the first result hasn't been parallelized, where the second has. If you have only one processor core, the results should be close. If you have more than two processor cores, the AsParallel call may increase performance even more. Also, you can read this article.

相关阅读:
Top