我编写了一个小型测试程序,并且很惊讶为什么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);
}
lock {}摘要:
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秒;秒 - 3.2秒,这快1秒。没有ThreadStatic和锁定 - 1.2秒。
我很好奇为什么这个简单示例中的[ThreadStatic]
属性会增加很多程序执行时间?
更新:我感到非常抱歉,但这些结果适用于DEBUG
版本。对于RELEASE
,我得到了完全不同的数字:(1.2; 2.4; 1.2)。对于DEBUG
,数字是(4.2; 3.2; 1.2)。
因此,对于RELEASE
版本,似乎没有[ThreadStatic]
性能损失。
答案 0 :(得分:8)
对于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
答案 1 :(得分:-1)
您有两行代码更新ms_Acc
。在lock
的情况下,你可以围绕这两个锁定,而在ThreadStatic
的情况下,每次访问ms_Acc
时都会发生一次,即每次迭代循环两次。这通常是使用lock
的好处,您可以选择所需的粒度。我猜测RELEASE构建优化了这种差异。
如果您将for循环更改为ms_Acc
的单一访问权限,我会很高兴看到性能是否变得非常相似或相同。