C# bool 型で否定演算子と比較演算子を使う場合の速度比較

C#のイメージ。

boolean 型の真偽を検証するとき、否定演算子と比較演算子のどちらのパフォーマンスが良いか検証しました。 否定演算子の方がパフォーマンスが良いのは想像が付いたのですが、どれだけの影響があるかを検証します。

ここでは C#, .NETFramework 4.5, Visual Studio を使って検証しています。

検証内容

次の 3 つのパターンで真偽値を検証します。1,000,000 回 (100万) 回の検証を 9 回試行し、 各回で処理の終了までにかかった時間を比較します。

パターン真偽値の検証方法
1if(value==false)
2if(value!=true)
3if(!value)

完全なソースコードはこのページの最後に掲載します。

検証結果

検証結果が次の通りです。処理時間は msec 単位です。何れもデバッグモードを有効にして実行しているため、 環境にも依りますが、実際にはもっと速度が出ます。

検証した結果当然のようにパターン 3 が高速であることが分かりました。 ミリ秒の 1 桁目までは影響が出ていませんからパフォーマンスを気にしないシチュエーションならそれほど気にならないかもしれません。

しかしながらパフォーマンスが求められるシステムに関しては、否定演算子の積極的な採用が望ましい可能性があります。 システム全体で見れば、真偽値の検証は多く実装されていることが容易に想像できるためです。

回数パターン1パターン2パターン3最速
12.6142.5742.3793
22.6162.4882.2933
32.6152.5262.2513
42.6292.7402.0923
52.6232.5142.1953
62.6172.5492.0563
72.7572.5412.0783
82.7832.5872.0603
92.5502.5512.0203

最適化による解決

C# / VisualStudio のプロジェクトプロパティから「コードの最適化」を有効にすると、いずれの方法でもあまり処理時間は変わりませんでした。 その他の環境でも同じようなことができると思われます。言語とビルド(コンパイル)環境が限定的になるかもしれませんが、こういったことでも解決することができます。

回数パターン1パターン2パターン3最速
12.0882.0732.0513
22.0062.2032.1201
32.0382.1122.0761
42.1132.0202.0982
52.6542.0892.3302
62.3812.2182.1063
72.2342.0182.0392
82.0282.0502.0421
92.0022.0052.1411

検証に用いたソースコード

Stopwatch stopwatch = new Stopwatch();
int times = 9;
int length = 1000000;

for (int loop = 1; loop <= times; loop++)
{
    bool value = true;
    double resultType1 = 0;
    double resultType2 = 0;
    double resultType3 = 0;

    stopwatch.Restart();

    for (int i = 0; i < length; i++)
    {
        if (value == false)
        {
            continue;
        }
        else
        {
            continue;
        }
    }

    stopwatch.Stop();

    resultType1 = (double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000d;

    stopwatch.Restart();

    for (int i = 0; i < length; i++)
    {
        if (value != true)
        {
            continue;
        }
        else
        {
            continue;
        }
    }

    stopwatch.Stop();

    resultType2 = (double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000d;

    stopwatch.Restart();

    for (int i = 0; i < length; i++)
    {
        if (!value)
        {
            continue;
        }
        else
        {
            continue;
        }
    }

    stopwatch.Stop();

    resultType3 = (double)stopwatch.ElapsedTicks / (double)Stopwatch.Frequency * 1000d;

    Console.WriteLine("|> " + loop + "|> {0:f3} |> {1:f3} |> {2:f3}",
                      resultType1, resultType2, resultType3);
}