LoginSignup
0
1

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. 準備した配列、リストに対して検証する。
    1. 単純にぐるぐる回す。
    2. ぐるぐる回しながら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