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 のスレッド ローカル アクセスごとに、CPU のコアの 1 つを 1.2 秒しか失うことはありません。スレッド ローカルは %fs レジスタを使用してアクセスされるため、関連するプロセッサ コマンドは 2 つだけです。
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コンパイラと比較するのは興味深いです)が、今でも問題は非常に良いIMHOです。