C# bool 型で否定演算子と比較演算子を使う場合の速度比較
boolean 型の真偽を検証するとき、否定演算子と比較演算子のどちらのパフォーマンスが良いか検証しました。 否定演算子の方がパフォーマンスが良いのは想像が付いたのですが、どれだけの影響があるかを検証します。
ここでは C#, .NETFramework 4.5, Visual Studio を使って検証しています。
検証内容
次の 3 つのパターンで真偽値を検証します。1,000,000 回 (100万) 回の検証を 9 回試行し、 各回で処理の終了までにかかった時間を比較します。
パターン | 真偽値の検証方法 |
---|---|
1 | if(value==false) |
2 | if(value!=true) |
3 | if(!value) |
完全なソースコードはこのページの最後に掲載します。
検証結果
検証結果が次の通りです。処理時間は msec 単位です。何れもデバッグモードを有効にして実行しているため、 環境にも依りますが、実際にはもっと速度が出ます。
検証した結果当然のようにパターン 3 が高速であることが分かりました。 ミリ秒の 1 桁目までは影響が出ていませんからパフォーマンスを気にしないシチュエーションならそれほど気にならないかもしれません。
しかしながらパフォーマンスが求められるシステムに関しては、否定演算子の積極的な採用が望ましい可能性があります。 システム全体で見れば、真偽値の検証は多く実装されていることが容易に想像できるためです。
回数 | パターン1 | パターン2 | パターン3 | 最速 |
---|---|---|---|---|
1 | 2.614 | 2.574 | 2.379 | 3 |
2 | 2.616 | 2.488 | 2.293 | 3 |
3 | 2.615 | 2.526 | 2.251 | 3 |
4 | 2.629 | 2.740 | 2.092 | 3 |
5 | 2.623 | 2.514 | 2.195 | 3 |
6 | 2.617 | 2.549 | 2.056 | 3 |
7 | 2.757 | 2.541 | 2.078 | 3 |
8 | 2.783 | 2.587 | 2.060 | 3 |
9 | 2.550 | 2.551 | 2.020 | 3 |
最適化による解決
C# / VisualStudio のプロジェクトプロパティから「コードの最適化」を有効にすると、いずれの方法でもあまり処理時間は変わりませんでした。 その他の環境でも同じようなことができると思われます。言語とビルド(コンパイル)環境が限定的になるかもしれませんが、こういったことでも解決することができます。
回数 | パターン1 | パターン2 | パターン3 | 最速 |
---|---|---|---|---|
1 | 2.088 | 2.073 | 2.051 | 3 |
2 | 2.006 | 2.203 | 2.120 | 1 |
3 | 2.038 | 2.112 | 2.076 | 1 |
4 | 2.113 | 2.020 | 2.098 | 2 |
5 | 2.654 | 2.089 | 2.330 | 2 |
6 | 2.381 | 2.218 | 2.106 | 3 |
7 | 2.234 | 2.018 | 2.039 | 2 |
8 | 2.028 | 2.050 | 2.042 | 1 |
9 | 2.002 | 2.005 | 2.141 | 1 |
検証に用いたソースコード
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);
}