Mur*_*ock 21 c# performance ienumerable benchmarking
一般来说IEnumerable<>
,当我传入参数时,我倾向于使用作为类型。然而,根据 BenchmarkDotNet:
[Benchmark]
public void EnumeratingCollectionsBad()
{
var list = new List<string>();
for (int i = 0; i < 1000; i++)
{
Bad(list);
}
}
[Benchmark]
public void EnumeratingCollectionsFixed()
{
var list = new List<string>();
for (int i = 0; i < 1000; i++)
{
Fixed(list);
}
}
private static void Bad(IEnumerable<string> list)
{
foreach (var item in list)
{
}
}
private static void Fixed(List<string> list)
{
foreach (var item in list)
{
}
}
Run Code Online (Sandbox Code Playgroud)
方法 | 工作 | 运行 | 意思 | 错误 | 标准差 | 中位数 | 第 0 代 | 第一代 | 第 2 代 | 已分配 |
---|---|---|---|---|---|---|---|---|---|---|
枚举集合坏 | .NET 核心 3.1 | .NET 核心 3.1 | 17.802 美元 | 0.3670 美元 | 1.0764 美元 | 17.338 美元 | 6.3782 | —— | —— | 40032乙 |
枚举集合固定 | .NET 核心 3.1 | .NET 核心 3.1 | 5.015 美元 | 0.1003 美元 | 0.2535 美元 | 4.860 美元 | —— | —— | —— | 32 乙 |
为什么接口版本会比具体版本慢得多(和内存密集型)?
Jon*_*eet 34
为什么接口版本会比具体版本慢得多(和内存密集型)?
当它使用接口时,迭代必须在堆上分配一个对象......而List<T>.GetEnumerator()
返回 a List<T>.Enumerator
,它是一个结构,不需要任何额外的分配。List<T>.Enumerator
implements IEnumerator<T>
,但因为编译器直接知道具体类型,所以不需要装箱。
因此,即使两种方法都在同一类型 (a List<T>
)的对象上运行,但仍会调用此方法:
IEnumerator<T> GetEnumerator()
Run Code Online (Sandbox Code Playgroud)
......有人称之为:
List<T>.Enumerator GetEnumerator()
Run Code Online (Sandbox Code Playgroud)
第一个几乎可以肯定只是委托给第二个,但必须将结果装箱,因为它IEnumerator<T>
是一个引用类型。
List<T>.GetEnumerator()
返回可变结构的事实可能会产生一些令人惊讶的后果,但它的设计正是为了获得您在此处看到的性能优势。
VS具体类型的使用界面可本身有一些很轻微的性能损失,但这里的主要原因是分配的差异。
归档时间: |
|
查看次数: |
1333 次 |
最近记录: |