D 中的线程局部变量非常快。这是我的测试。
64 位 Ubuntu,核心 i5,dmd v2.052 编译器选项:dmd -O -release -inline -m64
// this loop takes 0m0.630s
void main(){
int a; // register allocated
for( int i=1000*1000*1000; i>0; i-- ){
a+=9;
}
}
// this loop takes 0m1.875s
int a; // thread local in D, not static
void main(){
for( int i=1000*1000*1000; i>0; i-- ){
a+=9;
}
}
因此,每 1000*1000*1000 个线程本地访问,我们只损失 1.2 秒的 CPU 内核之一。使用 %fs 寄存器访问线程本地 - 所以只涉及几个处理器命令:
使用 objdump -d 反汇编:
- this is local variable in %ecx register (loop counter in %eax):
8: 31 c9 xor %ecx,%ecx
a: b8 00 ca 9a 3b mov $0x3b9aca00,%eax
f: 83 c1 09 add $0x9,%ecx
12: ff c8 dec %eax
14: 85 c0 test %eax,%eax
16: 75 f7 jne f <_Dmain+0xf>
- this is thread local, %fs register is used for indirection, %edx is loop counter:
6: ba 00 ca 9a 3b mov $0x3b9aca00,%edx
b: 64 48 8b 04 25 00 00 mov %fs:0x0,%rax
12: 00 00
14: 48 8b 0d 00 00 00 00 mov 0x0(%rip),%rcx # 1b <_Dmain+0x1b>
1b: 83 04 08 09 addl $0x9,(%rax,%rcx,1)
1f: ff ca dec %edx
21: 85 d2 test %edx,%edx
23: 75 e6 jne b <_Dmain+0xb>
也许编译器可以更聪明,并在循环之前将线程本地缓存到寄存器并在最后将其返回到线程本地(与 gdc 编译器进行比较很有趣),但即使是现在,恕我直言,事情还是非常好的。