0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C#】ループステートメントの速度を検証してみた その2

Last updated at Posted at 2020-09-01

前回、C#におけるループステートメントの速度検証をまとめてみました。検証方法が未熟な箇所が多々あったため、今回は@Midoliyさんにご紹介いただきましたBenchmarkDotNetを用いて検証を実施します。

実施すること

  1. 1億個の要素を持った配列およびリストを用意する。
  2. 準備した配列、リストに対して検証する。
  3. 単純にぐるぐる回す。
  4. ぐるぐる回しながら2の倍数を足し込んでいく。

対象のループステートメント

  1. for
  2. foreach
  3. do
  4. do-while
  5. LINQ(Query形式):足し込み検証のみ実施
  6. LINQ(Method形式):足し込み検証のみ実施

結果

単純にぐるぐる回す(配列)

                 Method |      Mean |      Error |     StdDev |    Median |

--------------------------- |----------:|-----------:|-----------:|----------:|
BenchFor_Array | 29.08 ms | 0.1590 ms | 0.1410 ms | 29.05 ms |
BenchForEach_Array | 48.22 ms | 0.0428 ms | 0.0334 ms | 48.22 ms |
BenchDo_Array | 28.93 ms | 0.0829 ms | 0.0735 ms | 28.93 ms |
BenchDoWhile_Array | 36.09 ms | 2.6406 ms | 7.7859 ms | 33.17 ms |

単純にぐるぐる回す(リスト)

                 Method |      Mean |      Error |     StdDev |    Median |

--------------------------- |----------:|-----------:|-----------:|----------:|
BenchFor_List | 36.53 ms | 0.4746 ms | 0.4439 ms | 36.40 ms |
BenchForEach_List | 248.81 ms | 10.3583 ms | 12.3308 ms | 244.77 ms |
BenchDo_List | 36.49 ms | 0.4889 ms | 0.4573 ms | 36.30 ms |
BenchDoWhile_List | 36.19 ms | 0.1416 ms | 0.1182 ms | 36.19 ms |
※配列とリストでforeachの速度がなぜここまで変わるのかは、@Tokeiyaさんの配列に対するforとforeachが非常にわかりやすかったです。

2の倍数の足し込み(配列)

                 Method |      Mean |      Error |     StdDev |    Median |

--------------------------- |----------:|-----------:|-----------:|----------:|
BenchForWithCalc_Array | 151.77 ms | 0.3014 ms | 0.2819 ms | 151.79 ms |
BenchForEachWithCalc_Array | 136.51 ms | 0.1996 ms | 0.1867 ms | 136.46 ms |
BenchDoWithCalc_Array | 151.72 ms | 0.2464 ms | 0.2305 ms | 151.65 ms |
BenchDoWhileWithCalc_Array | 151.03 ms | 1.1535 ms | 1.0225 ms | 150.97 ms |
BenchLINQQuery_Array | 611.51 ms | 5.0230 ms | 4.6985 ms | 613.74 ms |
BenchLINQMethod_Array | 589.09 ms | 11.6493 ms | 11.4412 ms | 586.88 ms |

2の倍数の足し込み(リスト)

                 Method |      Mean |      Error |     StdDev |    Median |

--------------------------- |----------:|-----------:|-----------:|----------:|
BenchForWithCalc_List | 169.25 ms | 0.3809 ms | 0.3563 ms | 169.37 ms |
BenchForEachWithCalc_List | 299.09 ms | 3.3102 ms | 3.0963 ms | 300.62 ms |
BenchDoWithCalc_List | 172.82 ms | 2.8077 ms | 2.1921 ms | 173.18 ms |
BenchDoWhileWithCalc_List | 169.38 ms | 0.5669 ms | 0.4734 ms | 169.22 ms |
BenchLINQQuery_List | 814.73 ms | 5.5605 ms | 5.2013 ms | 816.72 ms |
BenchLINQMethod_List | 825.85 ms | 7.5451 ms | 6.6885 ms | 825.91 ms |

Mean   : Arithmetic mean of all measurements
Error  : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)

検証ソース

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Generic;
using System.Linq;

namespace Benchmarks
{
    public class LoopBenchmarkTest
    {
        private static readonly int listCnt = 100_000_000;  // 要素数
        private static readonly int[] numArray;             // 検証配列
        private static readonly List<int> numList;          // 検証リスト

        static LoopBenchmarkTest()
        {
            numArray = Enumerable.Range(0, listCnt).ToArray();
            numList = new List<int>(numArray);
        }

#region Array
        [Benchmark]
        public long BenchFor_Array()
        {
            for (var i = 0; i <= numArray.Length - 1; i++) {}
            return 0;
        }

        [Benchmark]
        public long BenchForEach_Array()
        {
            foreach (var num in numArray) {}
            return 0;
        }

        [Benchmark]
        public long BenchDo_Array()
        {
            var i = 0;
            while (i <= numArray.Length - 1)
            {
                i++;
            }
            return 0;
        }

        [Benchmark]
        public long BenchDoWhile_Array()
        {
            var i = 0;
            do
            {
                i++;
            }
            while (i <= numArray.Length - 1);
            return 0;
        }
#endregion

#region List
        [Benchmark]
        public long BenchFor_List()
        {
            for (var i = 0; i <= numList.Count - 1; i++) {}
            return 0;
        }

        [Benchmark]
        public long BenchForEach_List()
        {
            foreach (var num in numList) {}
            return 0;
        }

        [Benchmark]
        public long BenchDo_List()
        {
            var i = 0;
            while (i <= numList.Count - 1)
            {
                i++;
            }
            return 0;
        }

        [Benchmark]
        public long BenchDoWhile_List()
        {
            var i = 0;
            do
            {
                i++;
            }
            while (i <= numList.Count - 1);
            return 0;
        }
#endregion

#region ArrayWithCalc
        [Benchmark]
        public long BenchForWithCalc_Array()
        {
            var total = 0;
            for (var i = 0; i <= numArray.Length - 1; i++)
            {
                if (i % 2 == 0)
                    total += numArray[i];
            }
            return total;
        }

        [Benchmark]
        public long BenchForEachWithCalc_Array()
        {
            var total = 0;
            foreach (var num in numArray)
            {
                if (num % 2 == 0)
                    total += num;
            }
            return total;
        }

        [Benchmark]
        public long BenchDoWithCalc_Array()
        {
            var i = 0;
            var total = 0;
            while (i <= numArray.Length - 1)
            {
                if (i % 2 == 0)
                    total += numArray[i];
                i++;
            }
            return total;
        }

        [Benchmark]
        public long BenchDoWhileWithCalc_Array()
        {
            var i = 0;
            var total = 0;
            do
            {
                if (i % 2 == 0)
                    total += numArray[i];
                i++;
            }
            while (i <= numArray.Length - 1);
            return total;
        }

        [Benchmark]
        public long BenchLINQQuery_Array()
        {
            var total = (
                from x in numArray
                where x % 2 == 0
                select (long)x
                ).Sum();
            return total;
        }

        [Benchmark]
        public long BenchLINQMethod_Array()
        {
            var total = numArray
                .Where(x => x % 2 == 0)
                .Sum(x => (long)x);
            return total;
        }
#endregion

#region ListWithCalc
        [Benchmark]
        public long BenchForWithCalc_List()
        {
            var total = 0;
            for (var i = 0; i <= numList.Count - 1; i++)
            {
                if (i % 2 == 0)
                    total += numList[i];
            }
            return total;
        }

        [Benchmark]
        public long BenchForEachWithCalc_List()
        {
            var total = 0;
            foreach (var num in numList)
            {
                if (num % 2 == 0)
                    total += num;
            }
            return total;
        }

        [Benchmark]
        public long BenchDoWithCalc_List()
        {
            var i = 0;
            var total = 0;
            while (i <= numList.Count - 1)
            {
                if (i % 2 == 0)
                    total += numList[i];
                i++;
            }
            return total;
        }

        [Benchmark]
        public long BenchDoWhileWithCalc_List()
        {
            var i = 0;
            var total = 0;
            do
            {
                if (i % 2 == 0)
                    total += numList[i];
                i++;
            }
            while (i <= numList.Count - 1);
            return total;
        }

        [Benchmark]
        public long BenchLINQQuery_List()
        {
            var total = (
                from x in numList
                where x % 2 == 0
                select (long)x
                ).Sum();
            return total;
        }

        [Benchmark]
        public long BenchLINQMethod_List()
        {
            var total = numList
                .Where(x => x % 2 == 0)
                .Sum(x => (long)x);
            return total;
        }
#endregion

    }

    class Program
    {
        static void Main(string[] args)
        {
            BenchmarkRunner.Run<LoopBenchmarkTest>();
        }
    }
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?