Местные нити в D действительно быстрые. Вот мои тесты.
64-битная Ubuntu, Core 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;
}
}
Таким образом, мы теряем только 1,2 секунды одного из ядер ЦП на 1000 *1000* 1000 локальных обращений потоков.
Доступ к локальным потокам осуществляется через регистр% 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),
но даже сейчас дело очень хорошее ИМХО.