我正在为 D 编程语言开发一个自定义标记释放样式的内存分配器,它通过从线程局部区域进行分配来工作。与代码的其他相同的单线程版本相比,线程本地存储瓶颈似乎导致从这些区域分配内存的速度大幅减慢(~50%),即使在将我的代码设计为每次分配仅进行一次 TLS 查找之后/解除分配。这是基于在循环中多次分配/释放内存,我试图弄清楚这是否是我的基准测试方法的产物。我的理解是,线程本地存储基本上应该只涉及通过额外的间接层访问某些内容,类似于通过指针访问变量。这是不正确的吗?线程本地存储通常有多少开销?
注意:虽然我提到了 D,但我也对不特定于 D 的一般答案感兴趣,因为如果 D 的线程本地存储实现比最佳实现慢,它可能会得到改进。
速度取决于 TLS 实施。
是的,您是对的,TLS 可以与指针查找一样快。在具有内存管理单元的系统上甚至可以更快。
对于指针查找,您需要调度程序的帮助。调度程序必须在任务切换时更新指向 TLS 数据的指针。
实现 TLS 的另一种快速方法是通过内存管理单元。这里,TLS 的处理方式与任何其他数据一样,但 TLS 变量是分配在特殊段中的。调度程序将在任务切换时将正确的内存块映射到任务的地址空间。
如果调度程序不支持任何这些方法,编译器/库必须执行以下操作:
- 获取当前线程Id
- 拿一个信号量
- 通过 ThreadId 查找指向 TLS 块的指针(可以使用映射等)
- 释放信号量
- 返回该指针。
显然,为每个 TLS 数据访问执行所有这些操作需要一段时间,并且可能需要最多三个操作系统调用:获取 ThreadId、获取和释放信号量。
顺便说一句,需要信号量来确保当另一个线程正在生成新线程时没有线程从 TLS 指针列表中读取。 (并因此分配一个新的 TLS 块并修改数据结构)。
不幸的是,在实践中 TLS 实现速度缓慢的情况并不少见。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)