我正在编写一个网格渲染管理器,认为将使用相同着色器的所有网格分组并在该着色器通道中一起渲染是个好主意。
目前我正在使用 foreach
循环,但想知道是否利用 LINQ 可以提高性能?
我正在编写一个网格渲染管理器,认为将使用相同着色器的所有网格分组并在该着色器通道中一起渲染是个好主意。
目前我正在使用 foreach
循环,但想知道是否利用 LINQ 可以提高性能?
为什么LINQ会更快呢?它内部也使用循环。
大多数情况下,因为引入了开销,LINQ会稍微慢一些。如果您非常关注性能,请不要使用LINQ。如果您想要更短、更易读、更易维护的代码,请使用LINQ。
LINQ-to-Objects通常会增加一些轻微的开销(多个迭代器等)。它仍然需要执行循环,而且需要委托调用,并且通常必须做一些额外的解引用才能访问捕获的变量等。在大多数代码中,这将几乎无法检测到,并且比简单易懂的代码所能承受的要多。
对于其他LINQ提供程序(如LINQ-to-SQL),由于查询可以在服务器上进行过滤,因此它应该比简单的foreach
好得多,但最可能你不会对整个"select * from foo"
进行操作,因此这并不一定是一个公平的比较。
关于PLINQ; 并行性可以减少经过的时间,但总CPU时间通常会稍微增加一些,因为需要管理线程等开销。
List<Foo>
)上使用LINQ,而是应该在这些集合上使用foreach
块。在这些情况下建议使用foreach
确实是有道理的。我的疑虑是:我是否只有在检测到性能问题时才应该用foreach
替换LINQ查询?今后,我将优先考虑使用foreach
。 - IAbstractLINQ现在较慢,但可能在某个时候会变得更快。 LINQ的好处在于您不必关心它如何工作。如果想出了一种非常快的新方法,Microsoft的人员可以实现它,而无需通知您,您的代码将更快。
更重要的是,LINQ更易于阅读。这应该足够理由。
需要注意的是,for
循环比 foreach
循环更快。所以对于原始帖子来说,如果你担心在类似渲染器这样的重要组件上的性能问题,请使用 for
循环。
我对这个问题很感兴趣,所以我刚才做了一个测试。在一台运行Microsoft Windows 7 Ultimate操作系统的Intel(R) Core(TM) i3-2328M CPU @ 2.20GHz,2200 Mhz,2 Core(s),并且有8GB RAM的计算机上,使用.NET Framework 4.5.2。
看起来LINQ可能比for each循环更快. 这里是我的测试结果:
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
}
LINQ
迭代器永远不会比foreach
更快。此外,List.Exists
不是LINQ方法。 - l33t.NET core 7即将发布,其中包括一些重要的更新,针对LINQ中的.Min、.Max、.Average和.Sum进行了性能优化。 参考链接: https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/#linq
如果与ForEach循环进行比较,则可以发现在.NET 6中,ForEach循环更快,在.NET 7中,LINQ方法更快:
这是使用BenchmarkDotNet进行基准测试的代码。
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
public class Program
{
public static void Main()
{
BenchmarkRunner.Run<ForEachVsLinq>();
}
}
[SimpleJob(RuntimeMoniker.Net60)]
[SimpleJob(RuntimeMoniker.Net70)]
[MemoryDiagnoser(false)]
public class ForEachVsLinq
{
private int[] _intArray;
[GlobalSetup]
public void Setup()
{
var random = new Random();
var randomItems = Enumerable.Range(0, 500).Select(_ => random.Next(999));
this._intArray = randomItems.ToArray();
}
[Benchmark]
public void ForEachMin()
{
var min = int.MaxValue;
foreach (var i in this._intArray)
{
if ( i < min)
min = i;
}
Console.WriteLine(min);
}
[Benchmark]
public void Min()
{
var min = this._intArray.Min();
Console.WriteLine(min);
}
[Benchmark]
public void ForEachMax()
{
var max = 0;
foreach (var i in this._intArray)
{
if (i > max)
max = i;
}
Console.WriteLine(max);
}
[Benchmark]
public void Max()
{
var max = this._intArray.Max();
Console.WriteLine(max);
}
[Benchmark]
public void ForEachSum()
{
var sum = 0;
foreach (var i in this._intArray)
{
sum += i;
}
Console.WriteLine(sum);
}
[Benchmark]
public void Sum()
{
var sum = this._intArray.Sum();
Console.WriteLine(sum);
}
}
foreach
。您的信息比较的是LINQ 6.0和LINQ 7.0,而问题是要比较LINQ和foreach
。您的比较与所问问题不相关,并且您的结论是不合乎逻辑的。 - Theodor Zouliasforeach
实现的基准测试,那就可以了。 - Theodor Zoulias