C 11: 4.8 `thread_local` Performans Ceza GCC?
G ÅŸimdiC 11
thread_local
anahtar sözcük; bu farklıdır uygular GNU__thread
izin öncelikle anahtar kelime dinamik başlatma ve yıkım anlambilim. Ne yazık ki, bu destek başvurular için çalıştırma cezası olmayan fonksiyon-yerel gerektirir Eğer dinamik başlatma gerek varsa.thread_local
bile değişkenler, kullanıcılar ile TLS değişkenler için__thread
kullanmaya devam etmek isteyebilir yani statik baÅŸlatma anlambilim.
Hassas doğası ve kökeni çalıştırma cezası nedir?
Açıkçası destek olmayan fonksiyon-yerel thread_local değişkenleri yok edilmesi gerek bir iş parçacığı başlatma aşamasından önce giriş için her iş parçacığı ana (gibi bir statik başlatma aşaması için genel değişkenler), ama onlar bağlıyordum için bazı çalışma cezası bunun dışında mı?
KonuÅŸma thread_local gcc yeni uygulama mimarisi nedir kabaca?
CEVAP
(Yasal Uyarı: GCC iç hakkında çok şey bilmiyorum, bu da bir tahmin.)
thread_local
dinamik başlatma 462819c taahhüt eklenir. Değişim biridir:
* semantics.c (finish_id_expression): Replace use of thread_local
variable with a call to its wrapper.
Çalıştırma cezası, thread_local
değişken her referans bir işlev çağrısı olacak. Basit bir test çalışması ile kontrol edelim:
// 3.cpp
extern thread_local int tls;
int main() {
tls = 37; // line 6
tls &= 11; // line 7
tls ^= 3; // line 8
return 0;
}
// 4.cpp
thread_local int tls = 42;
Derlenmiş*, biz görüyoruzhertls
referans kullanımı tembel bir kez değişken başlatma _ZTW3tls
, çağıran bir işlev olur:
00000000004005b0 <main>:
main():
4005b0: 55 push rbp
4005b1: 48 89 e5 mov rbp,rsp
4005b4: e8 26 00 00 00 call 4005df <_ZTW3tls> // line 6
4005b9: 8b 10 mov edx,DWORD PTR [rax]
4005bb: 83 c2 25 add edx,0x25
4005be: 89 10 mov DWORD PTR [rax],edx
4005c0: e8 1a 00 00 00 call 4005df <_ZTW3tls> // line 7
4005c5: 8b 10 mov edx,DWORD PTR [rax]
4005c7: 83 e2 0b and edx,0xb
4005ca: 89 10 mov DWORD PTR [rax],edx
4005cc: e8 0e 00 00 00 call 4005df <_ZTW3tls> // line 8
4005d1: 8b 10 mov edx,DWORD PTR [rax]
4005d3: 83 f2 03 xor edx,0x3
4005d6: 89 10 mov DWORD PTR [rax],edx
4005d8: b8 00 00 00 00 mov eax,0x0 // line 9
4005dd: 5d pop rbp
4005de: c3 ret
00000000004005df <_ZTW3tls>:
_ZTW3tls():
4005df: 55 push rbp
4005e0: 48 89 e5 mov rbp,rsp
4005e3: b8 00 00 00 00 mov eax,0x0
4005e8: 48 85 c0 test rax,rax
4005eb: 74 05 je 4005f2 <_ZTW3tls 0x13>
4005ed: e8 0e fa bf ff call 0 <tls> // initialize the TLS
4005f2: 64 48 8b 14 25 00 00 00 00 mov rdx,QWORD PTR fs:0x0
4005fb: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc
400602: 48 01 d0 add rax,rdx
400605: 5d pop rbp
400606: c3 ret
Bu ekstra sarıcı olmaz __thread
sürümü ile karşılaştırın:
00000000004005b0 <main>:
main():
4005b0: 55 push rbp
4005b1: 48 89 e5 mov rbp,rsp
4005b4: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc // line 6
4005bb: 64 8b 00 mov eax,DWORD PTR fs:[rax]
4005be: 8d 50 25 lea edx,[rax 0x25]
4005c1: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc
4005c8: 64 89 10 mov DWORD PTR fs:[rax],edx
4005cb: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc // line 7
4005d2: 64 8b 00 mov eax,DWORD PTR fs:[rax]
4005d5: 89 c2 mov edx,eax
4005d7: 83 e2 0b and edx,0xb
4005da: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc
4005e1: 64 89 10 mov DWORD PTR fs:[rax],edx
4005e4: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc // line 8
4005eb: 64 8b 00 mov eax,DWORD PTR fs:[rax]
4005ee: 89 c2 mov edx,eax
4005f0: 83 f2 03 xor edx,0x3
4005f3: 48 c7 c0 fc ff ff ff mov rax,0xfffffffffffffffc
4005fa: 64 89 10 mov DWORD PTR fs:[rax],edx
4005fd: b8 00 00 00 00 mov eax,0x0 // line 9
400602: 5d pop rbp
400603: c3 ret
Bu sarıcı thread_local
Her durumda kullanmak için gerekli değildir. Bu decl2.c
açığa çıkarılabilir.
Sarıcı sadece oluşturulur:
deÄŸilfonksiyon-yerel ve,
extern
(yukarıda gösterilen örnek), ya da- Bu tür önemsiz olmayan bir yıkıcı
__thread
değişkenler için izin verilmez) - Tipi değişken sabit olmayan ifade Bir da
__thread
değişkenler için izin verilmez) tarafından başlatıldı.
Tüm diğer durumlarda, __thread
ile aynı davranır. Bu, extern __thread
bazı değişkenler olmadığı sürece, performans kaybı olmadan thread_local
__thread
tümünü değiştir anlamına gelir.
*: İnliner fonksiyon sınırı daha az fark edilebilir çünkü O0 ile derlenmiş. Eğer açarsak bile-O3 bu başlatma kontrolleri hala devam etmektedir.
64-bit ile 32-bit döngü sayısı bir değ...
Hızlı performans: dizileri sıralama...
DateTime.Şimdi en iyi şekilde ölçmek i...
HTTP vs HTTPS performans...
Ben ve C arasında performans farkı var...