Сравните скорости LINQ для разных подходов в C#
В этом примере сравниваются скорости LINQ при использовании LINQ различными способами.
Чтобы найти минимальные и максимальные значения X в List & lt; Point & gt;, пример Использование LINQ для поиска ограничивающего прямоугольника для списка PointF в C# определяет запрос LINQ, который выбирает X-координаты из списка. Затем я использую методы LINQ Min и Max в запросе. (Он повторяет эти шаги, чтобы найти минимальное и максимальное значения Y.)
Когда вы нажимаете кнопку Go, этот пример сравнивает эту технику с несколькими другими. Следующий код показывает первый тест.
Stopwatch watch = new Stopwatch(); // Найти минимальное и максимальное значения в 2 запросах. watch.Reset(); watch.Start(); int xmin = (from Point p in points select p.X).Min(); int xmax = (from Point p in points select p.X).Max(); watch.Stop(); txt2Queries.Text = watch.Elapsed.TotalSeconds.ToString("0.00") + " sec"; Refresh();
Этот код создает и запускает Секундомер. Затем он использует два запроса LINQ, оба из которых выбирают координаты X из списка случайных структур Point. В коде используются методы расширения запросов Следующий код показывает второе испытание. Этот тест создает один запрос для выбора значений X, а затем использует его методы Min и Max. Если вы посмотрите на изображение выше, вы увидите, что этот метод имеет в основном те же самые характеристики, что и предыдущий метод. Следующий код показывает третий тест. Этот код создает запрос LINQ, как и раньше. Он вызывает метод ToArray запроса для копирования координат X в массив. Затем он использует методы массива Min и Max, чтобы найти наименьшие и наибольшие значения. Идея здесь заключалась в том, что, возможно, предыдущие тесты потратили время на создание списка значений X дважды. Если вы посмотрите на изображение выше, вы увидите, что этот метод занимает значительно больше времени, чем предыдущие методы, поэтому создание массива явно не помогло. Следующий код показывает четвертый тест. Этот код находит минимальное и максимальное значения, перейдя через массив с помощью цикла for. Если вы посмотрите на изображение, вы увидите, что этот метод занял менее половины времени, чем самые быстрые методы LINQ. Это не должно удивлять. Вы не используете LINQ, потому что это быстро, вы используете его, потому что это легко. Написание петель сами бесполезно, но если вам нужна дополнительная производительность (и обычно вы этого не делаете), то это того стоит. Следующий код показывает окончательный тест. Этот код находит минимальное и максимальное значения, используя цикл foreach. Это занимает примерно столько же времени, сколько цикл для. // Найдите минимальное и максимальное значения в 1 повторном запросе.
watch.Reset();
watch.Start();
var x_query = from Point p in points select p.X;
xmin = x_query.Min();
xmax = x_query.Max();
watch.Stop();
txt1Query.Text =
watch.Elapsed.TotalSeconds.ToString("0.00") +
" sec";
Refresh();
// Найдите минимальное и максимальное значения с массивом.
watch.Reset();
watch.Start();
var arr_query = from Point p in points select p.X;
int[] xs = arr_query.ToArray();
xmin = xs.Min();
xmax = xs.Max();
watch.Stop();
txtArray.Text =
watch.Elapsed.TotalSeconds.ToString("0.00") +
" sec";
Refresh();
// Найдите минимальное и максимальное значения с помощью цикла.
watch.Reset();
watch.Start();
xmin = points[0].X;
xmax = xmin;
for (int i = 1; i < points.Length; i++)
{
if (xmin > points[i].X) xmin = points[i].X;
if (xmax < points[i].X) xmax = points[i].X;
}
watch.Stop();
txtLoop.Text =
watch.Elapsed.TotalSeconds.ToString("0.00") +
" sec";
Refresh();
// Найдите минимальное и максимальное значения с помощью цикла foreach.
watch.Reset();
watch.Start();
xmin = points[0].X;
xmax = xmin;
foreach (Point pt in points)
{
if (xmin > pt.X) xmin = pt.X;
if (xmax < pt.X) xmax = pt.X;
}
watch.Stop();
txtForeach.Text =
watch.Elapsed.TotalSeconds.ToString("0.00") +
" sec";
Refresh();