4 ms·
This is missing out on considerations re. tls-model=local-dynamic and visibility; making variables non-preemptible by declaring them static or visibility("hidde
by eqvinox 2y ago
This is missing out on considerations re. tls-model=local-dynamic and visibility; making variables non-preemptible by declaring them static or visibility("hidden"/"internal") significantly reduces TLS cost.
https://www.akkadia.org/drepper/tls.pdf https://www.akkadia.org/drepper/tls.pdf is the go-to reference for TLS models, cf. first paragraph of each subsection of section 4.
- quotemstr 2y agoAs well as other costs. That we default to global visibility is another one of the ossified defaults the article mentions. One of the first things I look at when trying to improve the performance of a C++ project is its linking setup --- most of the time, people are using the terrible ELF defaults and paying in code size and execution time for something they don't need.
- yosefk 2y ago-ftls-model=local-dynamic barely changes the generated code compared to the default (global-dynamic); you no longer have data16 prefixes around the call to __tls_get_addr (which means this call can't be replaced with something cheaper if you don't put the .o into a .so in the end) but otherwise it's the same. -fvisiblity=hidden / __attribute__ ((visibility ("hidden"))) doesn't seem to do anything. Are you sure that either of these speeds up TLS access for thread_locals defined in shared libraries?
- eqvinox 2y agoIf I remember correctly, local-dynamic is relevant if you access multiple thread-local variables, as the offset between them will be constant. The visibility attributes should allow the compiler to switch from global-dynamic to local-dynamic automatically. It's been a bit since I looked at all of this. Also note that these sequences are highly architecture dependent and cost as well as cost differences will vary e.g. for ARM or ARM64.
- yosefk 2y agoI updated the post with the point on visibility; in my tests inspired by https://lobste.rs/s/b5dnjh/0_0_0_c_thread_local_storage_performance#c_dkzbw3 https://lobste.rs/s/b5dnjh/0_0_0_c_thread_local_storage_perf... I see that clang improves codegen thanks to hidden visibility but g++ does not, and that comment says clang doesn't do it on all platforms. I stick to the broad conclusion that thread_locals without constructors linked into an executable rather than a shared library are the fastest and most performance-portable by far, but the visibility point is very worth mentioning.