1

質問は優雅さよりもパフォーマンスの問題です、私は自分自身のために覗き見します、しかし...

実装するための両方のオプションがあり、CPUの計算が高速であるか、最終的に同じである場合(私はそう思う傾向がありますが、条件は(x <10)同じです)

    public int DidLogcount = 0; // DidLogCount is raised by +1 every time we deside, then condition is met 
    public bool MoreLogsAllowed()
    {
        if (DidLogcount < 10) return true;
        else return false;
    }

vs

    public bool MoreLogsAllowed()
    {
       return DidLogcount < 10;
    }

ほとんどの場合、nullでないかどうかを確認することを想定していますが、必要な場合は両方のケースでクラウドになります。他の問題を見逃していなければ、絞り込んだ(?)と思います。

正解を申し上げます。どうも。

再試行:正解をマークしたかったのですが、さらに3つ読み込まれたページを更新しました...

より多くの投票を待つつもりです...そして今のところ、私は本当にすべてに感謝したいと思います!あなたの知識を共有するために、それは私の心を通り抜けました、コンパイラによる最適化の問題、それで...それらのプリントアウトを持っていることはそれ自体では少しの違いはありますが何かを示していますが、条件の山に追加されるとそれは少なくなります少し、本当に複雑なアプリについて話していない限り、私は大きくは言いません。それでも、パフォーマンスの問題は決して小さな問題ではありません。実際にテストしてくれた@Steveと@Nickのおかげで、ロジックと読みやすさも向上しています。

4

6 に答える 6

5

パフォーマンスに違いがあるかどうかはわかりませんが、あるとしても無視できる程度です。しかし、2番目のケースはよりエレガントです。

于 2012-08-30T12:37:56.887 に答える
4

LinqPADでテスト済み。

int DidLogcount = 5;
void Main()
{
    MoreLogsAllowed();
    MoreLogsAllowed2();
}

public bool MoreLogsAllowed() 
{ 
    if (DidLogcount < 10) return true; 
    else return false; 
} 

public bool MoreLogsAllowed2() 
{ 
    return (DidLogcount < 10); 
} 

このILコードを生成します

IL_0000:  ldarg.0     
IL_0001:  call        UserQuery.MoreLogsAllowed
IL_0006:  pop         
IL_0007:  ldarg.0     
IL_0008:  call        UserQuery.MoreLogsAllowed2

MoreLogsAllowed:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery.DidLogcount
IL_0006:  ldc.i4.s    0A 
IL_0008:  bge.s       IL_000C
IL_000A:  ldc.i4.1    
IL_000B:  ret         
IL_000C:  ldc.i4.0    
IL_000D:  ret         

MoreLogsAllowed2:
IL_0000:  ldarg.0     
IL_0001:  ldfld       UserQuery.DidLogcount
IL_0006:  ldc.i4.s    0A 
IL_0008:  clt         
IL_000A:  ret    

2番目のバージョンは、よりエレガントであるだけでなく、より短いコードを生成するようです。
これがLinqPADによって導入された違いではないことを確認するために、Visual Studio 2010を使用して小さなコンソールアプリケーションを作成し、リリースモードのデフォルト設定でコンパイルしました。
次に、ILDASMを使用してILコールドを確認しました。
上記のコードは、コンパイラで生成されたコードと同じであることを確認します。
もちろん、違いはごくわずかですが、2つのバージョンは同じILコードを生成しません。

于 2012-08-30T12:42:57.490 に答える
2

私のように、最初の例には優雅さはありません。さらに、コンパイラーは最初のケースを最適化すると思うので、パフォーマンスについて話すことは何もありません。私にとって、2番目の例は、より簡潔で、短く、読みやすいものです。

于 2012-08-30T12:40:07.527 に答える
2

2つの選択肢の間にパフォーマンスの違いがあった場合、私は非常に驚きます。私も2番目の選択肢がよりエレガントで、括弧を省略します。

ただし、より複雑な条件では、特に関数呼び出しが含まれる場合、2つのreturnステートメントを異なる行に配置すると、デバッガーを使用してコードをステップ実行しているときに何が起こっているかを確認するのが少し便利になります。

于 2012-08-30T12:43:18.867 に答える
2

パフォーマンスの違いはおそらく無視でき、.NET JITコンパイルに大きく依存しますが、x86の例を見ると、比較は次のようになります。

                if (DidLogcount < 10) return true;
... skipped DidLogCount call...
    00000020  mov         dword ptr [ebp-4],eax 
    00000023  cmp         dword ptr [ebp-4],0Ah 
    00000027  jge         00000037 
    00000029  mov         eax,1 
    0000002e  and         eax,0FFh 
    00000033  mov         esp,ebp 
    00000035  pop         ebp 
    00000036  ret 
                else return false;
    00000037  xor         eax,eax 
    00000039  mov         esp,ebp 
    0000003b  pop         ebp 
    0000003c  ret 

vs

            return (DidLogcount < 10);
    ... skipped DidLogCount call...
0000001f  mov         dword ptr [ebp-4],eax 
00000022  cmp         dword ptr [ebp-4],0Ah 
00000026  setl        al 
00000029  movzx       eax,al 
0000002c  mov         esp,ebp 
0000002e  pop         ebp 
0000002f  ret 

後者の方がおそらく非常に高速ですが、CPUがこれらの命令をどのように処理するかによって異なります。

最良の答えは、それを測定するためのテストアプリケーションを作成することです。

于 2012-08-30T12:53:31.697 に答える
0

最も重要なのはMSILであるため、2つのフラグメントに違いはありません。コンパイル後、この場合、コンパイルされたコードは同一です。

Code 1 C# -> MSIL 1 -> Code natif 1

Code 2 C# -> MSIL 1 -> Code natif 1
于 2012-08-30T12:45:23.933 に答える