DevStudio 2005 を使用した結果は次のとおりです。
デバッグ:
- ブロックなし: 25.109
- ブロック付:19.703
リリース:
DevStudio 内からではなく、コマンド ラインからこれを実行することが非常に重要です。DevStudio は、アプリのパフォーマンスに影響を与える何らかの処理を行います。
実際に何が起こっているのかを知る唯一の方法は、アセンブラー コードを見ることです。リリースで生成されたアセンブラは次のとおりです。
FindWithoutBlock:
00401000 xor eax,eax
00401002 cmp dword ptr [ecx+eax*4],0F4240h
00401009 je FindWithoutBlock+1Ah (40101Ah)
0040100B add eax,1
0040100E cmp eax,186A0h
00401013 jl FindWithoutBlock+2 (401002h)
00401015 mov eax,186A0h
0040101A ret
コンパイラが ArrLen パラメーターを削除し、定数に置き換えたことに注意してください。それも機能として残しています。
コンパイラが他の関数 (FindWithBlock) で行ったことは次のとおりです。
004010E0 mov dword ptr [esp+38h],186A0h
004010E8 mov ebx,0F4240h
004010ED mov dword ptr [esi+61A80h],ebx
004010F3 xor eax,eax
004010F5 cmp dword ptr [esi],ebx
004010F7 je main+0EFh (40110Fh)
004010F9 lea esp,[esp]
00401100 add eax,1
00401103 cmp dword ptr [esi+eax*4],ebx
00401106 jne main+0E0h (401100h)
00401108 cmp eax,186A0h
0040110D je main+0F5h (401115h)
0040110F call dword ptr [__imp__getchar (4020D0h)]
00401115 sub dword ptr [esp+38h],1
0040111A jne main+0CDh (4010EDh)
ここでは、関数がインライン化されています。これlea esp,[esp]
は、次の命令を整列するための 7 バイトの nop です。コードは、インデックス 0 を他のすべてのインデックスとは別にチェックしますが、メイン ループは FindWithoutBlock バージョンよりも間違いなくタイトです。
うーん。FindWithoutBlock を呼び出すコードは次のとおりです。
0040106F mov ecx,edi
00401071 mov ebx,eax
00401073 call FindWithoutBlock (401000h)
00401078 mov ebp,eax
0040107A mov edi,186A0h
0040107F cmp ebp,186A0h
00401085 je main+6Dh (40108Dh)
00401087 call dword ptr [__imp__getchar (4020D0h)]
0040108D sub edi,1
00401090 jne main+5Fh (40107Fh)
あはは!FindWitoutBlock 関数が呼び出されるのは 1 回だけです。コンパイラは、関数が毎回同じ値を返すことを発見し、1 回の呼び出しに最適化しました。FindWithBlock では、検索の前に配列に書き込むため、コンパイラは同じ仮定を行うことができません。したがって、配列は呼び出しごとに (潜在的に) 異なります。
これをテストするには、次のvolatile
ようなキーワードを追加します:-
int FindWithoutBlock(volatile int * Arr, int ArrLen, int Val)
{
for ( int i = 0; i < ArrLen; i++ )
if ( Arr[i] == Val )
return i;
return ArrLen;
}
int FindWithBlock(volatile int * Arr, int LastCellIndex, int Val)
{
Arr[LastCellIndex] = Val;
int i;
for ( i = 0 ; Arr[i] != Val; i++ );
return i;
}
これを行うと、両方のバージョンが同じ時間 (6.040) に実行されます。メモリ アクセスが主要なボトルネックであるため、FindWithoutBlock のより複雑なテストは全体の速度には影響しません。