Подтвердить что ты не робот

Почему Array.Sort() настолько медленный по сравнению с LINQ?

Я сделал приложение для быстрого тестирования, чтобы сравнить сортировку 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 SECONDS!

Все массивы отсортированы (LINQ создает новую коллекцию и оставляет несогласованный массив oryginal), но Array.Sort очень медленный! Как это можно объяснить? (в режиме DEBUG и RELEASE Array.Sort не работает)

Я приклеил код с выражением лямбда при сортировке с Array.Sort, но это то же самое с и без него. (Class Person реализует интерфейс IComparable)

4b9b3361

Ответ 1

Ваш запрос Linq даже не выполняется, потому что вы не получите результаты. Это называется отсроченное исполнение. Запрос выполняется только при фактическом перечислении результатов.

Используйте что-то вроде var results = sort.ToArray() для выполнения запроса, тогда вы получите более точные результаты.

Ответ 2

LINQ ленив. Ваш people2 на самом деле не был отсортирован, LINQ только что создал временный "объект обещания", который будет отсортирован. Чтобы это произошло на самом деле, вам нужно заставить оценку Console.WriteLine отсортировать результат, преобразовать его в список/массив или сделать что-нибудь еще подобное.

Подробнее: отложенное исполнение.

Ответ 3

Операторы Linq возвращают IEnumerable<T> или flavors of, это (или что-либо с использованием ключевого слова yield) выполняется только при его повторном запуске. Большинство действий, доступных из библиотек Linq (не все) являются ленивыми/отложенными.

Вы не повторяете его, так что вы фактически не выполняете сортировку.

Вам нужно принудительно выполнить полную итерацию. Придерживание результатов в списке будет полностью переименовывать возвращаемый список:

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();

Ответ 4

Попробуйте изменить эту часть и повторите тест.

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

Это будет оценивать выражение LINQ.