14

私は小さなテスト プログラムを作成しましたが、lock {}ソリューションがロックフリーよりも高速に実行されるのに、[ThreadStatic]静的変数よりも属性が高いことに驚きました。

[ThreadStatic] スニペット:

[ThreadStatic]
private static long ms_Acc;
public static void RunTest()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    int one = 1;
    for (int i = 0; i < 100 * 1000 * 1000; ++i) {
        ms_Acc += one;
        ms_Acc /= one;
    }
    stopwatch.Stop();
    Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds);
}

ロック {} スニペット:

private static long ms_Acc;
private static object ms_Lock = new object();
public static void RunTest()
{
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    int one = 1;
    for (int i = 0; i < 100 * 1000 * 1000; ++i) {
        lock (ms_Lock) {
            ms_Acc += one;
            ms_Acc /= one;
        }
    }
    stopwatch.Stop();
    Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds);
}

私のマシンでは、最初のスニペットに 4.2 秒かかりました。秒 - 1 秒速い 3.2 秒。ThreadStatic とロックなし - 1.2 秒。

[ThreadStatic]この単純な例の属性によって、プログラムの実行時間が大幅に増加するのはなぜでしょうか?

更新:大変申し訳ありませんが、これらの結果はDEBUGビルド用です。1つにはRELEASE、まったく異なる数値 (1.2; 2.4; 1.2) が得られました。数値はDEBUG(4.2; 3.2; 1.2)でした。

そのため、ビルドの場合、パフォーマンスの低下RELEASEはないようです。[ThreadStatic]

4

2 に答える 2

11

RELEASE ビルドでは、[ThreadStatic] パフォーマンスの低下はほとんどないようです(最新の CPU ではわずかな低下のみ)。

の逆アセンブル コードを次にms_Acc += one示します。最適RELEASE化が有効になっている場合:

いいえ [ThreadStatic]DEBUG:

00000060  mov         eax,dword ptr [ebp-40h] 
00000063  add         dword ptr ds:[00511718h],eax 

いいえ [ThreadStatic]RELEASE:

00000051  mov         eax,dword ptr [00040750h]
00000057  add         eax,dword ptr [rsp+20h]
0000005b  mov         dword ptr [00040750h],eax

[ThreadStatic]DEBUG:

00000066  mov         edx,1 
0000006b  mov         ecx,4616E0h 
00000070  call        664F7450 
00000075  mov         edx,1 
0000007a  mov         ecx,4616E0h 
0000007f  mov         dword ptr [ebp-50h],eax 
00000082  call        664F7450 
00000087  mov         edx,dword ptr [eax+18h] 
0000008a  add         edx,dword ptr [ebp-40h] 
0000008d  mov         eax,dword ptr [ebp-50h] 
00000090  mov         dword ptr [eax+18h],edx 

[ThreadStatic]RELEASE:

00000058  mov         edx,1 
0000005d  mov         rcx,7FF001A3F28h 
00000067  call        FFFFFFFFF6F9F740 
0000006c  mov         qword ptr [rsp+30h],rax 
00000071  mov         rbx,qword ptr [rsp+30h] 
00000076  mov         ebx,dword ptr [rbx+20h] 
00000079  add         ebx,dword ptr [rsp+20h] 
0000007d  mov         edx,1 
00000082  mov         rcx,7FF001A3F28h 
0000008c  call        FFFFFFFFF6F9F740 
00000091  mov         qword ptr [rsp+38h],rax 
00000096  mov         rax,qword ptr [rsp+38h] 
0000009b  mov         dword ptr [rax+20h],ebx 
于 2011-08-23T07:10:19.283 に答える
-1

を更新する 2 行のコードがありますms_Acc。このlock場合、これらの両方に単一のロックがありますが、このThreadStatic場合、 へのアクセスごとにms_Acc1 回、つまりループの反復ごとに 2 回発生します。これは一般的に を使用する利点でありlock、必要な粒度を選択できます。RELEASE ビルドがこの違いを最適化したと推測しています。

for ループを への 1 回のアクセスに変更した場合、パフォーマンスが非常に類似するか、または同一になるかどうかを確認したいと思いますms_Acc

于 2011-08-23T05:42:41.967 に答える