Является ли оператор LINQ быстрее цикла 'foreach'? - PullRequest
103 голосов
/ 01 июля 2010

Я пишу менеджер рендеринга сетки и подумал, что было бы неплохо сгруппировать все сетки, которые используют один и тот же шейдер, и затем рендерить их, пока я нахожусь в этом проходе шейдера.

В настоящее время я использую цикл foreach, но мне интересно, может ли использование LINQ повысить производительность?

Ответы [ 8 ]

186 голосов
/ 01 июля 2010

Почему LINQ должен быть быстрее? Он также использует циклы внутри.

В большинстве случаев LINQ будет немного медленнее, потому что это приводит к накладным расходам. Не используйте LINQ, если вы заботитесь о производительности. Используйте LINQ, потому что вам нужен более короткий, удобочитаемый и обслуживаемый код.

55 голосов
/ 01 июля 2010

LINQ-to-Objects обычно собирается добавить некоторые предельные издержки (несколько итераторов и т. Д.).Он по-прежнему должен выполнять циклы, и имеет вызовы делегатов, и , как правило, должны делать некоторые дополнительные разыменования для получения перехваченных переменных и т. Д. В большинстве кодов это практически невозможно обнаружитьи больше, чем , предоставляемый более простым для понимания кодом.

С другими поставщиками LINQ, такими как LINQ-to-SQL, тогда, поскольку запрос может фильтроваться на сервере, он должен быть очень большим лучше , чем квартира foreach, но, скорее всего, вы бы не сделали одеяло "select * from foo" в любом случае , так что не обязательно справедливое сравнение *.1019 *

Re PLINQ;параллелизм может сократить время истекшее , но общее время ЦП обычно немного увеличивается из-за накладных расходов на управление потоками и т. д.

16 голосов
/ 01 июля 2010

Я думаю, что LINQ лучше использовать через цикл foreach, потому что он дает вам намного более чистый и понятный код. Но LINQ медленнее, чем foreach. Чтобы получить больше, просмотрите статью LINQ против FOREACH против FOR Loop Performance .

14 голосов
/ 01 июля 2010

LINQ теперь медленнее, но в какой-то момент он может стать быстрее. В LINQ хорошо то, что вам не нужно заботиться о том, как он работает. Если придумать новый метод, который невероятно быстр, люди в Microsoft могут реализовать его, даже не сказав вам, и ваш код будет намного быстрее.

Что еще более важно, LINQ просто намного легче читать. Этого должно быть достаточно для причины.

10 голосов
/ 18 октября 2011

Следует, вероятно, отметить, что цикл for быстрее, чем foreach.Так что для оригинального поста, если вы беспокоитесь о производительности на критическом компоненте, таком как рендерер, используйте цикл for.

Ссылка: В .NET, который работает быстрее'for' или 'foreach'?

9 голосов
/ 01 июля 2010

Вы можете получить повышение производительности, если будете использовать параллельный LINQ для многоядерных процессоров. См. Parallel LINQ (PLINQ) (MSDN).

3 голосов
/ 13 декабря 2017

Это на самом деле довольно сложный вопрос. Linq делает некоторые вещи очень простыми: если вы реализуете их самостоятельно, вы можете запутаться (например, linq .Except ()). Это особенно относится к PLinq, и особенно к параллельной агрегации, реализованной PLinq.

Обычно для идентичного кода linq будет работать медленнее из-за накладных расходов при вызове делегата.

Однако, если вы обрабатываете большой массив данных и применяете относительно простые вычисления к элементам, вы получите значительное увеличение производительности, если:

  1. Вы используете массив для хранения данных.
  2. Вы используете цикл for для доступа к каждому элементу (в отличие от foreach или linq).

    • Примечание. При проведении сравнительного анализа, пожалуйста, помните: если вы используете один и тот же массив / список для двух последовательных тестов, кэш ЦП сделает второй быстрее *
2 голосов
/ 13 ноября 2017

Меня заинтересовал этот вопрос, поэтому я только что прошел тест.Использование .NET Framework 4.5.2 на процессоре Intel® Core iM2328M с тактовой частотой 2,20 ГГц, 2200 МГц, 2 ядра (ов) с оперативной памятью 8 ГБ под управлением Microsoft Windows 7 Ultimate.* Похоже, что LINQ может быть быстрее, чем для каждого цикла. Вот результаты, которые я получил:

Exists = True
Time   = 174
Exists = True
Time   = 149

Было бы интересно, если бы некоторые из вас могли скопировать и вставить этот код в консольное приложение.и проверить тоже.Перед тестированием с объектом (Сотрудник) я попробовал тот же тест с целыми числами.LINQ там тоже был быстрее.

public class Program
{
    public class Employee
    {
        public int id;
        public string name;
        public string lastname;
        public DateTime dateOfBirth;

        public Employee(int id,string name,string lastname,DateTime dateOfBirth)
        {
            this.id = id;
            this.name = name;
            this.lastname = lastname;
            this.dateOfBirth = dateOfBirth;

        }
    }

    public static void Main() => StartObjTest();

    #region object test

    public static void StartObjTest()
    {
        List<Employee> items = new List<Employee>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(new Employee(i,"name" + i,"lastname" + i,DateTime.Today));
        }

        Test3(items, items.Count-100);
        Test4(items, items.Count - 100);

        Console.Read();
    }


    public static void Test3(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item.id == idToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test4(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Exists(e => e.id == idToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion


    #region int test
    public static void StartIntTest()
    {
        List<int> items = new List<int>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(i);
        }

        Test1(items, -100);
        Test2(items, -100);

        Console.Read();
    }

    public static void Test1(List<int> items,int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item == itemToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test2(List<int> items, int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Contains(itemToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...