簡體   English   中英

Enumerable.Range與for循環的性能

[英]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;
}

我發現了以下問題:

  1. 為什么Enumerable.Range比直接收益循環快?

  2. 可枚舉范圍執行

  3. 關於帶有Enumerable.Range vs傳統for循環的foreach的思考

但是我擔心最后使用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時,實際上我可能會循環兩次

查看參考源 .RangeRepeat都以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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM