Является ли оператор LINQ быстрее, чем цикл foreach?
Я пишу менеджер Mesh Rendering и думал, что было бы неплохо сгруппировать все ячейки, которые используют один и тот же шейдер, а затем визуализировать их, пока я нахожусь в этом шейдерном проходе.
В настоящее время я использую цикл foreach
, но задавался вопросом, может ли использование LINQ увеличить производительность?
Ответы
Ответ 1
Почему LINQ будет быстрее? Он также использует петли внутри.
В большинстве случаев LINQ будет немного медленнее, потому что он вводит накладные расходы. Не используйте LINQ, если вы заботитесь о производительности. Используйте LINQ, потому что вам нужен более удобный для чтения и поддерживаемый код.
Ответ 2
LINQ-to-Objects обычно добавляет некоторые предельные накладные расходы (несколько итераторов и т.д.). Он по-прежнему должен делать циклы и имеет делегировать вызовы и обычно должен выполнять некоторые дополнительные разыгрывания, чтобы получить захваченные переменные и т.д. В большинстве кодов это будет практически невозможно обнаружить и более чем доступно более простому пониманию кода.
С другими поставщиками LINQ, такими как LINQ-to-SQL, тогда, поскольку запрос может фильтроваться на сервере, он должен быть намного лучше, чем плоский foreach
, но, скорее всего, вы бы не сделали одеяло "select * from foo"
в любом случае, так что это не обязательно справедливое сравнение.
Re PLINQ; parallelism может сократить прошедшее время, но общее время процессора обычно немного увеличивается из-за накладных расходов на управление потоками и т.д.
Ответ 3
Я думаю, что LINQ лучше использовать в цикле foreach
, потому что он дает вам гораздо более чистый и понятный код. Но LINQ медленнее, чем foreach
. Чтобы получить больше, просмотрите статью LINQ vs FOREACH vs FOR Loop Performance.
Ответ 4
LINQ работает медленнее, но в какой-то момент он может ускориться. Хорошая вещь о LINQ заключается в том, что вам не нужно заботиться о том, как это работает. Если новый метод считается невероятно быстрым, люди в Microsoft могут реализовать его, даже не сообщая вам, и ваш код будет намного быстрее.
Более того, LINQ гораздо проще читать. Этого должно быть достаточно.
Ответ 5
Вы можете повысить производительность, если используете параллельные LINQ для нескольких ядер. См. Параллельный LINQ (PLINQ) (MSDN).
Ответ 6
Следует, наверное, отметить, что цикл for
быстрее, чем foreach
. Поэтому для исходного сообщения, если вас беспокоит производительность на критическом компоненте, например рендерере, используйте цикл for
.
Ссылка:
В .NET, какой цикл работает быстрее, 'for' или 'foreach'?
Ответ 7
Мне был интересен этот вопрос, поэтому я сделал тест только сейчас. Использование .NET Framework 4.5.2 на процессоре i3-2328M с процессором Intel (R) Core i3-2328M с частотой 2,20 ГГц, 2200 МГц, 2 ядрами с 8 ГБ оперативной памяти, работающей под управлением Microsoft Windows 7 Ultimate.
Похоже, что LINQ может быть быстрее, чем для каждого цикла. Вот результаты, которые я получил:
Exists=True
Time=174
Exists=True
Time=149
Было бы интересно, если бы некоторые из вас могли скопировать и вставить этот код в консольное приложение и протестировать.
Перед тестированием с объектом (Employee) я попробовал один и тот же тест с целыми числами. 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
}
Ответ 8
Это довольно сложный вопрос. Linq делает некоторые вещи очень простыми, что если вы их сами реализуете, вы можете наткнуться (например, linq.Except()). Это особенно относится к PLinq, и особенно к параллельной агрегации, реализованной PLinq.
В общем случае для идентичного кода linq будет медленнее из-за накладных расходов на вызов делегата.
Если, однако, вы обрабатываете большой массив данных и применяете относительно простые вычисления к элементам, вы получите огромное увеличение производительности, если: