主要观点:讨论如何确保对 TLS(线程局部存储)的访问快速,介绍了新的 C++ 分析器 funtrace 及其追踪功能,重点阐述了 C++中thread_local
关键字的使用及相关性能问题,包括构造函数对thread_local
访问的影响、共享库中thread_local
的处理、__tls_get_addr
函数的作用及性能问题等,并给出了一些性能优化建议和未来工作方向。
关键信息:
funtrace
可追踪函数调用、返回及线程状态变化,软件追踪分析器需为每个线程提供追踪数据缓冲区,共享缓冲区在某些情况下太慢,thread_local
关键字适合追踪缓冲区。- 访问带有构造函数的
thread_local
对象会先检查线程局部“保护变量”,若未设置则调用构造函数,内联只在同一翻译单元定义时发生,不同情况下thread_local
的访问代码不同。 - 共享库中的
thread_local
变量处理更复杂,需要函数调用获取 TLS 区域地址,data16
可能只是为了适配不同链接情况而添加的填充指令。 __tls_get_addr
函数用于获取thread_local
变量地址,其存在导致性能问题,如多次调用、懒分配等,不同优化选项和编译参数对thread_local
性能影响不同。
重要细节:- 不同编译和链接选项下
thread_local
的代码生成及性能表现,如-O3
优化、-fPIC
、-shared
等。 __tls_get_addr
函数的内部实现及懒分配机制。- 各种避免
__tls_get_addr
性能问题的“脏技巧”,如“内联”pthread_getspecific
、使用-ftls-model=initial-exec
等。 - 相关编译器和运行时问题导致的
__tls_get_addr
性能更差,如多次调用、dlopen 后性能退化等。
性能指南总结:
- 无构造函数的
thread_local
对象访问效率高,构造函数会降低效率,尤其是访问外部翻译单元的extern thread_local
。 -fPIC
编译和-shared
链接会使 TLS 访问变慢,构造函数与它们结合会更慢。- 优先将数据放入一个
thread_local
对象,定义为隐藏可见性可能有帮助。
未来工作:希望避免__tls_get_addr
的代价,寻找更高效的处理方式,如针对 Python 扩展模块的解决方案。
总之,thread_local
在 C++中的使用存在性能问题,需要注意各种编译和链接选项以及相关函数的使用,以提高性能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。