22

我制作了快速测试应用程序,将 LINQ 排序与自定义对象上的 Array.Sort 进行比较。Array.Sort 似乎非常慢!

我制作了这样的自定义类:

class Person : IComparable<Person>
{
    public int Age { get; set; }
    public string Name { get; set; }

    public int CompareTo(Person obj)
    {
        return this.Age.CompareTo(obj.Age);
    }

    public Person()
    { }

}

然后我在 main() 中做了我的测试人员:

string name = "Mr. Tomek";

Random r = new Random();
int size = 10000000;

DateTime start, end;
Person[] people1 = new Person[size];
Person[] people2 = new Person[size];

for (int i = 0; i < size; i++)
{
     people1[i] = new Person();
     people1[i].Age = r.Next(0, 10000);
     people1[i].Name = name;

     people2[i] = new Person();
     people2[i].Age = people1[i].Age;
     people2[i].Name = people1[i].Name;
}

之后,我测量了按 Array.Sort 和 LINQ 排序的时间:

start = DateTime.Now;
var sort = from s in people2
           orderby s.Age
           select s;
end = DateTime.Now;
Console.WriteLine("LINQ: ");
Console.WriteLine((end - start).TotalMilliseconds);

start = DateTime.Now;
Array.Sort(people1,((Person p1, Person p2)=>{return p1.CompareTo(p2);}));
end = DateTime.Now;

Console.WriteLine("IComparable: ");
Console.WriteLine((end - start).TotalMilliseconds);

Console.ReadLine();

Linq 时间:大约 1 或 2 毫秒

Array.Sort:超过 16秒!

所有数组都已排序(LINQ 生成新集合,原始数组未排序),但 Array.Sort 非常慢!怎么解释?(在 DEBUG 和 RELEASE 模式下 Array.Sort 极度失败)

我在使用 Array.Sort 排序时粘贴了带有 lambda 表达式的代码,但无论有没有它都是一样的。(类 Person 实现 IComparable 接口)

4

4 回答 4

56

你的 Linq 查询甚至没有被执行,因为你没有得到结果。这称为延迟执行。仅当您实际枚举结果时才会执行查询。

使用类似的东西var results = sort.ToArray()来执行查询,然后你会得到更准确的结果。

于 2012-04-24T14:00:31.810 回答
14

LINQ 是懒惰的。你people2实际上并没有被排序,LINQ 只是创建了一个临时的“承诺对象”,它将排序。为了让它真正发生,你必须强制对Console.WriteLine排序结果进行评估,将其转换为列表/数组或做任何其他类似的事情。

查看更多:延迟执行

于 2012-04-24T14:01:19.263 回答
9

Linq 语句返回IEnumerable<T>或风格, this (或使用yield关键字的任何内容)仅在您迭代它时执行。Linq 库中可用的大多数操作(不是全部)都是惰性/延迟的。

你没有迭代它,所以你实际上并没有执行排序。

您需要强制进行完整的迭代。将结果粘贴在 List 中将完全迭代返回的枚举:

var sort = (from s in people2
            orderby s.Age
            select s).ToList();

只有这样,您才会将苹果与苹果进行比较。

事实上,orderby排序(

var sort = from s in people2
           orderby s.Age
           select s;

var s = sort.First();
于 2012-04-24T14:01:48.220 回答
1

尝试更改这部分并再次进行测试。

    start = DateTime.Now;
    var sort = (from s in people2
               orderby s.Age
               select s).ToList();
    end = DateTime.Now;

这将评估 LINQ 表达式。

于 2012-04-24T14:09:07.183 回答