Mor*_*eng 11 c# performance ienumerable range enumerable
下面的代码是检查执行相同解决方案的三种不同方式的性能.
public static void Main(string[] args)
{
// for loop
{
Stopwatch sw = Stopwatch.StartNew();
int accumulator = 0;
for (int i = 1; i <= 100000000; ++i)
{
accumulator += i;
}
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, accumulator);
}
//Enumerable.Range
{
Stopwatch sw = Stopwatch.StartNew();
var ret = Enumerable.Range(1, 100000000).Aggregate(0, (accumulator, n) => accumulator + n);
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, ret);
}
//self-made IEnumerable<int>
{
Stopwatch sw = Stopwatch.StartNew();
var ret = GetIntRange(1, 100000000).Aggregate(0, (accumulator, n) => accumulator + n);
sw.Stop();
Console.WriteLine("time = {0}; result = {1}", sw.ElapsedMilliseconds, ret);
}
}
private static IEnumerable<int> GetIntRange(int start, int count)
{
int end = start + count;
for (int i = start; i < end; ++i)
{
yield return i;
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
time = 306; result = 987459712
time = 1301; result = 987459712
time = 2860; result = 987459712
Run Code Online (Sandbox Code Playgroud)
因为Enumerable.Aggregate需要更多的方法调用,所以"for循环"比其他两个解决方案更快也就不足为奇了.然而,"Enumerable.Range"比"自制IEnumerable"更快,这让我感到惊讶.我认为Enumerable.Range比简单的GetIntRange方法有更多的开销.
这有什么可能的原因?
yfe*_*lum 11
为什么Enumerable.Range
要比你的自制慢GetIntRange
?实际上,如果Enumerable.Range
被定义为
public static class Enumerable {
public static IEnumerable<int> Range(int start, int count) {
var end = start + count;
for(var current = start; current < end; ++current) {
yield return current;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后它应该和你自制的一样快GetIntRange
.这实际上是参考实现Enumerable.Range
,没有编译器或程序员的任何技巧.
您可能希望将您GetIntRange
和System.Linq.Enumerable.Range
以下实现进行比较(当然,正如Rob指出的那样,在发布模式下进行编译).关于编译器将从迭代器块生成的内容,可以稍微优化该实现.
public static class Enumerable {
public static IEnumerable<int> Range(int start, int count) {
return new RangeEnumerable(start, count);
}
private class RangeEnumerable : IEnumerable<int> {
private int _Start;
private int _Count;
public RangeEnumerable(int start, int count) {
_Start = start;
_Count = count;
}
public virtual IEnumerator<int> GetEnumerator() {
return new RangeEnumerator(_Start, _Count);
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
private class RangeEnumerator : IEnumerator<int> {
private int _Current;
private int _End;
public RangeEnumerator(int start, int count) {
_Current = start - 1;
_End = start + count;
}
public virtual void Dispose() {
_Current = _End;
}
public virtual void Reset() {
throw new NotImplementedException();
}
public virtual bool MoveNext() {
++_Current;
return _Current < _End;
}
public virtual int Current { get { return _Current; } }
object IEnumerator.Current { get { return Current; } }
}
}
Run Code Online (Sandbox Code Playgroud)
我的猜测是你在调试器中运行.以下是我的结果,从命令行使用"/ o +/debug-"构建
time = 142; result = 987459712
time = 1590; result = 987459712
time = 1792; result = 987459712
Run Code Online (Sandbox Code Playgroud)
仍有一点点差异,但并不是那么明显.迭代器块实现不如定制解决方案那么高效,但它们非常好.
归档时间: |
|
查看次数: |
6503 次 |
最近记录: |