什么是 CLR 循环优化行为?
What is CLR loop optimization behavior?
我想知道如果我用 foreach 遍历一个数组,JITter 稍后会用简单的 for 循环替换 foreach 循环以减少枚举器惩罚,这是真的吗?如果是,那么 List
呢?因为列表由数组支持。
最后,Linq 的优化是什么,请考虑以下内容:
var result = typeof(List<int>).GetInterfaces()
.FirstOrDefault(i => i.IsGenericType);
这会得到任何优化吗?
在 .NET 4.7.2650 上的 C# 2.8.2(应该是最新的 2018 年 7 月 25 日):
数组上的for
和foreach
已完全优化,
List<T>
上的 for
通过内联 .Count
和索引器 []
的代码得到了完全优化。
您可以在 sharplab 上看到它,右窗格:方法 ArrayFor
、ArrayForEach
和 ListFor
不调用外部方法(但 ListFor
具有调用 ThrowArgumentOutOfRangeException
方法的代码,即由索引器 []
) 进行的调用。 ListForEach
调用了 System.Collections.Generic.List``1+Enumerator[[System.Int32, mscorlib]].MoveNext()
所以它不是完全内联的。 EnumerableForEach
没有可以看到方法名称的显式调用,因为通过使用接口,它可以直接使用方法的地址(参见各种 call dword [0x218a0084]
、call dword [0x218a0088]
...)
据我所知,
- 你可以确定数组 上的
foreach
会被优化掉
- Foreach
List<T>
不会 被优化
- 迭代
IEnumerable<T>
和 linq 不会 被优化
但是优化在很大程度上取决于编译器及其版本,因此最好的方法是使用编译器并在简单情况下检查 IL 代码。
我想知道如果我用 foreach 遍历一个数组,JITter 稍后会用简单的 for 循环替换 foreach 循环以减少枚举器惩罚,这是真的吗?如果是,那么 List
呢?因为列表由数组支持。
最后,Linq 的优化是什么,请考虑以下内容:
var result = typeof(List<int>).GetInterfaces()
.FirstOrDefault(i => i.IsGenericType);
这会得到任何优化吗?
在 .NET 4.7.2650 上的 C# 2.8.2(应该是最新的 2018 年 7 月 25 日):
数组上的
for
和foreach
已完全优化,List<T>
上的for
通过内联.Count
和索引器[]
的代码得到了完全优化。
您可以在 sharplab 上看到它,右窗格:方法 ArrayFor
、ArrayForEach
和 ListFor
不调用外部方法(但 ListFor
具有调用 ThrowArgumentOutOfRangeException
方法的代码,即由索引器 []
) 进行的调用。 ListForEach
调用了 System.Collections.Generic.List``1+Enumerator[[System.Int32, mscorlib]].MoveNext()
所以它不是完全内联的。 EnumerableForEach
没有可以看到方法名称的显式调用,因为通过使用接口,它可以直接使用方法的地址(参见各种 call dword [0x218a0084]
、call dword [0x218a0088]
...)
据我所知,
- 你可以确定数组 上的
foreach
会被优化掉 - Foreach
List<T>
不会 被优化 - 迭代
IEnumerable<T>
和 linq 不会 被优化
但是优化在很大程度上取决于编译器及其版本,因此最好的方法是使用编译器并在简单情况下检查 IL 代码。