C# 文字列の文字数カウントで「foreach」と「Linq」と「Replace」と「Split」と「Regex」のパフォーマンスを計測して比較する

  • 作成日 2022.08.19
  • C#
C# 文字列の文字数カウントで「foreach」と「Linq」と「Replace」と「Split」と「Regex」のパフォーマンスを計測して比較する

C#で、文字列の文字数カウント処理を「foreach」と「Linq」と「Replace」と「Split」と「Regex」のそれぞれで実行したパフォーマンスを計測して比較するコードと結果を記述してます。

環境

  • OS windows11 pro 64bit
  • Microsoft Visual Studio Community 2022 Version 17.2.3

パフォーマンス計測

「System.Diagnostics.Stopwatch」を使用して、文字列の文字数カウント処理で「foreach」と「Linq」と「Replace」と「Split」と「Regex」を100万回実行して、計測した結果を比較してみます。

using System;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
    internal class Program
    {

        private const int n = 1_000_000;

        static void Main(string[] args)
        {

            string str = "mebee";
            int count = 0;

            var time = new System.Diagnostics.Stopwatch();

            // 計測開始
            time.Start();

            for (int i = 0; i < n; i++)
            {
                foreach (char c in str)
                {
                    if (c == 'e')
                    {
                        count++;
                    }
                }
                count = 0;
            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"foreach : {time.ElapsedMilliseconds}ms");


            // 計測開始
            time.Reset(); // リセット
            time.Start();

            for (int i = 0; i < n; i++)
            {
                count = str.Count(v => v == 'e');
                count = 0;

            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"Linq : {time.ElapsedMilliseconds}ms");

            // 計測開始
            time.Reset(); // リセット
            time.Start();

            for (int i = 0; i < n; i++)
            {
                count = str.Where(x => (x == 'e')).Count();
                count = 0;

            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"Linq Where : {time.ElapsedMilliseconds}ms");

            // 計測開始
            time.Reset(); // リセット
            time.Start();

            for (int i = 0; i < n; i++)
            {
                count = str.Length - str.Replace("e".ToString(), "").Length;
                count = 0;

            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"Replace : {time.ElapsedMilliseconds}ms");


            // 計測開始
            time.Reset(); // リセット
            time.Start();

            for (int i = 0; i < n; i++)
            {
                count = str.Split('e').Length - 1;
                count = 0;

            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"Split : {time.ElapsedMilliseconds}ms");

            // 計測開始
            time.Reset(); // リセット
            time.Start();

            for (int i = 0; i < n; i++)
            {
                count = Regex.Matches(str, 'e'.ToString()).Count;
                count = 0;

            }

            time.Stop();

            System.Diagnostics.Debug.WriteLine($"Regex : {time.ElapsedMilliseconds}ms");


        }
    }
}

実行結果をみると「foreach」を使用した方が、速そうです。

【1回目】
foreach : 32ms
Linq : 65ms
Linq Where : 120ms
Replace : 69ms
Split : 93ms
egex : 1125ms

【2回目】
foreach : 37ms
Linq : 68ms
Linq Where : 120ms
Replace : 66ms
Split : 101ms
Regex : 1063ms

【3回目】
foreach : 30ms
Linq : 73ms
Linq Where : 109ms
Replace : 74ms
Split : 81ms
Regex : 1152ms