C# AsParallel-Linq Where子句中的前后性能

C# AsParallel-Linq Where子句中的前后性能,c#,linq,plinq,C#,Linq,Plinq,我有一个列表集合,每个老板都有2到10名助理员工。我把所有的员工都分组,包括老板。现在我有了列表,从这里我使用并行LINQ搜索“Raj”,在where子句之前或之后,我可以在哪里放置支持方法aspallel(),以获得更好的性能 public class Person { public int EmpID { get; set; } public string Name { get; set; } public string Department { get; set;

我有一个
列表
集合,每个老板都有2到10名助理员工。我把所有的员工都分组,包括老板。现在我有了
列表
,从这里我使用并行LINQ搜索“Raj”,在where子句之前或之后,我可以在哪里放置支持方法
aspallel()
,以获得更好的性能

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();
}
公共类人物
{
公共int EmpID{get;set;}
公共字符串名称{get;set;}
公共字符串部门{get;set;}
公共字符串{get;set;}
}
void Main()
{
List BossList=新列表()
{
新老板()
{
EmpID=101,
Name=“Harry”,
Department=“开发”,
性别=“男性”,
雇员=新名单()
{
新人(){EmpID=102,Name=“Peter”,Department=“Development”,Gender=“Male”},
新人(){EmpID=103,Name=“Emma Watson”,Department=“Development”,Gender=“Female”},
}
},
新老板()
{
EmpID=104,
Name=“Raj”,
Department=“开发”,
性别=“男性”,
雇员=新名单()
{
新人(){EmpID=105,Name=“Kaliya”,Department=“Development”,Gender=“Male”},
新人(){EmpID=103,Name=“Emma Watson”,Department=“Development”,Gender=“Female”},
}
}
};
列表结果=BossList
.SelectMany(x=>
新[]{newperson{Name=x.Name,Department=x.Department,Gender=x.Gender,EmpID=x.EmpID}}
.Concat(x名雇员))
.GroupBy(x=>x.EmpID)//按员工ID分组
.Select(g=>g.First())//并为每个唯一的员工选择一个实例
.ToList();
List SelectedResult=新建列表();
//AsParallel()-Before Where子句
SelectedResult=result.AsParallel()。其中(m=>m.Name.ToLowerInvariant()。包含(“Raj.ToLowerInvariant())。ToList();
//AsParallel()-Where子句之后
SelectedResult=result.Where(m=>m.Name.ToLowerInvariant().Contains(“Raj.ToLowerInvariant()).AsParallel().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();
List SelectedResult=new List();
//AsParallel()-Before Where子句
SelectedResult=result.AsParallel()。其中(m=>m.Name.ToLowerInvariant()。包含(“Raj.ToLowerInvariant())。ToList();
//AsParallel()-Where子句之后
SelectedResult=result.Where(m=>m.Name.ToLowerInvariant().Contains(“Raj.ToLowerInvariant()).AsParallel().ToList();
之前

AsParallel帮助我们并行运行查询,这使并行线程能够提高性能。如果将WHERE子句放在WHERE子句之前,则过滤将以串联方式完成,只有这样,所有内容才会并行化

下面是一些测试代码:

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;
   }
}
结果:

Count: 989 in 10574ms
Count: 989 in 1409ms
很明显,第一个结果没有被并行化,而第二个结果却被并行化了。如果只有一个处理器内核,结果应该很接近。如果您有两个以上的处理器内核,那么AsParallel调用可能会进一步提高性能。
此外,您还可以阅读本文。

在本例中,使用AsParallel将是一种真正的过度使用。你读过佩奇吗?如果您能提供更多关于实际问题的信息(例如:实际上,一切都在SqlServer数据库中),您应该对其进行基准测试。剩下的纯粹是猜测。