[c#]yieldは本当に遅いのか

2021-05-19

これ使われているプログラムを見て「ナニコレ?」となったのは記憶に新しい。個人的にはこの単語見るたびに某刈り取る歌が脳内に流れる。

話は脱線したが、今回はこの「yield」について検証していこうと思う。単語を日本語訳すると「産み出す」とか「実る」とかそういう意味合いである。その意味通り、通るたびに戻り値を1つ産み出していく処理だ。この処理はc#では痒い所に手が届く便利なメソッドとなる。

ただし、このメソッド遅いらしい。個人的にはそんな遅いと感じたことはないが、なんか遅いらしい。

この記事ではyieldを使用するとどれくらい遅くなるのか具体的に検証してみる。

yieldありとなしで実行時間を比較してみる

1億回繰り返した時の速度を比較してみる

…と、いうわけでこんなコード書きました。

using System;
using System.Collections.Generic;

namespace ConsoleApp9
{
    class Program
    {
        private const int Num = 100000000;
        static void Main()
        {
            List<int> nums = new List<int>();
            List<int> nums2 = new List<int>();
            var start = DateTime.Now;
            for (var i = 0; i < Num; i++)
            {
                nums.Add(i);
            }
            var end = DateTime.Now;

            var start2 = DateTime.Now;
            nums2.AddRange(GetNum());
            var end2 = DateTime.Now;

            var j = nums[0];
            var k = nums2[0];

            Console.WriteLine($"yieldなし:{end-start}");
            Console.WriteLine($"yieldあり:{end2-start2}");
            Console.ReadLine();
        }
        public static IEnumerable<int> GetNum()
        {
            for (var i=0; i < Num; i++) {
                yield return i;
            }
        }
    }
}

実行結果

yieldありだと2秒遅くなった。一億回で2秒ならまあ…そんなに気にならない範囲ではあります。

ただ、もっと処理を入れるとさらに差は大きく響いてきます。
当たり前ですがルートの計算とかじゃんじゃん入れたらこれよりも差は大きくなりました。

今のところyieldでないとどうしても実装できない、という状況が思い浮かばないのでひとまず使わない方向で問題ないのではないでしょうか。