我正在编写一个“网格渲染”管理器,并认为最好将所有使用同一着色器的网格进行分组,然后在我通过该着色器通道时进行渲染。
我目前正在使用foreach
循环,但想知道使用LINQ是否可以提高性能?
我正在编写一个“网格渲染”管理器,并认为最好将所有使用同一着色器的网格进行分组,然后在我通过该着色器通道时进行渲染。
我目前正在使用foreach
循环,但想知道使用LINQ是否可以提高性能?
Answers:
为什么LINQ应该更快?它还在内部使用循环。
在大多数情况下,LINQ会慢一些,因为它会引入开销。如果您非常关心性能,请不要使用LINQ。使用LINQ是因为您需要较短的更好可读性和可维护性的代码。
LINQ-to-Objects 通常会增加一些边际开销(多个迭代器等)。它仍然必须执行循环,并具有委托调用,并且通常将不得不做一些额外的解引用才能获取捕获的变量等。在大多数代码中,这实际上是不可检测的,并且比简单易懂的代码所提供的更多。
对于LINQ-to-SQL之类的其他LINQ提供程序,则由于查询可以在服务器上进行过滤,因此它应该比flat 过滤器好得多foreach
,但是"select * from foo"
无论如何,您很可能不会做完所有的覆盖,因此不一定公平比较。
Re PLINQ; 并行性可以减少经过的时间,但是由于线程管理等开销,总的CPU时间通常会稍微增加。
List<Foo>
;相反,我应该foreach
在这些集合上使用一个块。foreach
在这些情况下使用的建议确实有意义。我的担心:foreach
如果我检测到性能问题,是否应该仅用LINQ查询替换?展望未来,我将考虑第foreach
一个。
我认为LINQ最好在foreach
循环中使用,因为它可以使您的代码更加简洁明了。但是LINQ比慢foreach
。要获取更多信息,请阅读文章LINQ vs FOREACH vs FOR Loop Performance。
LINQ现在比较慢,但是在某些时候可能会变快。LINQ的优点在于您不必关心它的工作方式。如果想出一种新方法非常快,那么Microsoft的人员甚至可以在不告诉您的情况下实施该新方法,并且您的代码会更快。
但是,更重要的是,LINQ更加易于阅读。那应该是足够的理由。
应该注意的是,for
循环比的速度更快foreach
。因此,对于原始帖子,如果您担心诸如渲染器之类的关键组件的性能,请使用for
循环。
如果将并行LINQ用于多核,则可能会提高性能。请参阅并行LINQ(PLINQ)(MSDN)。
我对这个问题很感兴趣,所以我刚才做了一个测试。在Intel(R)i3-2328M CPU @ 2.20GHz,2200 Mhz,2个Core和具有8GB ram的Microsoft Windows 7 Ultimate上使用.NET Framework 4.5.2。
看起来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
}
Exists=True Time=184 Exists=True Time=135
在Apache Gaming笔记本电脑(Win 10,C#7.3)上得到了它。编译并以调试模式运行。如果我逆转考试,我会得到Exists=True Time=158 Exists=True Time=194
。我猜似乎Linq更优化了。