[英]Thoughts on foreach with Enumerable.Range vs traditional for loop
[英]Performance of Enumerable.Range vs for loop
我想知道使用Enumerable.Range
会反对使用foreach
循环带来的性能开销。 例如:
var stringArray = Enumerable.Range(0, 4).Select(i => string.Empty).ToArray();
VS.
var stringArray = new string[4];
for (int i = 0; i < formatted.Length; i++)
{
stringArray[i] = string.Empty;
}
我发现了以下问题:
但是我担心最后使用Select
时,实际上我可能会循环两次。 但是,我喜欢使用Range
选项的优雅之处。
通过以下测试, for
更加有效:(以毫秒为单位,相差+ -3 ms-无关紧要。)
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Range(0, 4).Select(i => string.Empty).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //3305
watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[4];
for (int i = 0; i < stringArray2.Length; i++)
{
stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1
但是您可以代替使用Enumerable.Range().Select
use .Repeat
:
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 4).ToArray();
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //391
说完上述注意事项后,您在这里谈论的是非常小的收藏(4件)。 在较大的集合中,尤其是如果删除.ToArray()
其行为将.ToArray()
不同:
var watch = System.Diagnostics.Stopwatch.StartNew();
var stringArra1y = Enumerable.Repeat(string.Empty, 100000);
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //360
watch = System.Diagnostics.Stopwatch.StartNew();
var stringArray2 = new string[100000];
for (int i = 0; i < stringArray2.Length; i++)
{
stringArray2[i] = string.Empty;
}
watch.Stop();
Console.WriteLine(watch.ElapsedTicks); //1335
但是我担心最后使用Select时,实际上我可能会循环两次
查看参考源 .Range
和Repeat
都以yield return
:
static IEnumerable<int> RangeIterator(int start, int count) {
for (int i = 0; i < count; i++) yield return start + i;
}
因此,它也延迟执行,就像.Select
一样,它不会循环两次。
并不是说使用Stopwatch
在每次运行时都会返回不同的结果,但是总体思路如上所述
IMO (尤其是在小型馆藏的情况下)由于其对性能的微小改进而易于阅读。 当您已经遇到性能问题时,仅在遇到更大的问题(例如,嵌套在List<>
上for
循环而不是使用HashSet<>
)之后,再处理类似的事情。
在我非常简单的测试中,对于100万个字符串,for循环看起来快了38ms。
static void Main(string[] args)
{
var start = DateTime.Now;
EnTest();
var end = DateTime.Now;
var firstResult = end - start;
Console.WriteLine("Difference for Enumerable: {0}ms", firstResult.Milliseconds);
GC.Collect();
Thread.Sleep(2000);
var secondStart = DateTime.Now;
ArTest();
var secondEnd = DateTime.Now;
var secondResult = secondEnd - secondStart;
Console.WriteLine("Difference for loop: {0}ms", secondResult.Milliseconds);
var globalResult = firstResult - secondResult;
Console.WriteLine("Difference between tests: {0}ms", globalResult.Milliseconds);
Console.ReadKey();
}
public static void EnTest()
{
var stringArray = Enumerable.Range(0, 1000000).Select(i => string.Empty).ToArray();
}
public static void ArTest()
{
var stringArray = new string[1000000];
for (int i = 0; i < stringArray.Length; i++)
{
stringArray[i] = string.Empty;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.