はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【C#, Unity】Regex.Matchはインスタンスメソッドを使うとGC.Allocと処理速度の面で有利

はじめに

Regex.Matchには静的メソッドインスタンスメソッドが存在します。

// 静的メソッド
Match match = Regex.Match("An extraordinary day dawns with each new day.", @"\ba\w*\b");

// インスタンスメソッド
Match match2 = new Regex(@"\ba\w*\b").Match("An extraordinary day dawns with each new day.");

静的メソッドの仕組みとして、公式ドキュメントには以下のように記載されています。

静的 Match(String, String, RegexOptions) メソッドは、コンストラクターを使用してオブジェクトを Regex 構築し、 Regex(String, RegexOptions) インスタンス Match(String) メソッドを呼び出すことと同じです。

Regex.Match メソッド (System.Text.RegularExpressions) | Microsoft Learn

つまり複数回同じPatternで利用する場合は、無駄なインスタンスが沢山生成されてしまうということになります。

GC.Alloc警察としてはけしからんとなるわけですが、本当にそうなのか実験してみたいと思います。

実験

UnityではどれくらいのGC.Allocが発生したか調べることができるので、Unity2022.2.1f1にて以下のコードを実行してみました。
(正しい比較になっていなかったので、コードを修正しました 2023/2/20)

public class Sample : MonoBehaviour
{
    private const string Pattern = @"\ba\w*\b";
    private const string Input = "An extraordinary day dawns with each new day.";
    private const int Count = 1000;
    private static readonly Regex Regex = new Regex(Pattern, RegexOptions.IgnoreCase);
    
    private void Update()
    {
        // GC.Alloc:332.0KB, Time ms:33.52
        for (var i = 0; i < Count; i++)
        {
            _ = Regex.Match(Input, Pattern, RegexOptions.IgnoreCase);
        }
    }
    
    private void Updat2()
    {
        // GC.Alloc:230.5KB, Time ms:29.84
        for (var i = 0; i < Count; i++)
        {
            _ = Regex.Match(Input);
        }
    }
}

GC.Allocと処理速度の面でインスタンスメソッドの方が勝っているようですね。

繰り返し利用する場合は特に理由がない限りインスタンスメソッドを利用すると良いでしょう。