本地线程分配缓冲_线程本地分配缓冲区

本地线程分配缓冲

最近,我一直在研究遭受严重性能问题的Java应用程序。 在许多问题中,真正引起我注意的一个问题是新对象的分配速度相对较慢(应用程序分配了大量的相当大的对象)。 后来发现,原因是大量的分配发生在TLAB之外。

什么是TLAB?

在Java中,新对象在Eden中分配。 这是线程之间共享的内存空间。 如果考虑到多个线程可以同时分配新对象,那么显然需要某种同步机制。 怎么解决呢? 分配队列? 某种互斥锁? 即使这些是不错的解决方案,也有更好的解决方案。 这是TLAB发挥作用的地方。 TLAB代表线程本地分配缓冲区,它是Eden内部的一个专为线程分配的区域。 换句话说,只有一个线程可以在该区域中分配新对象。 每个线程都有自己的TLAB。 因此,只要在TLAB中分配对象,就不需要任何类型的同步。 在TLAB内部进行分配很简单
指针缓冲 (这就是为什么有时称为指针缓冲分配)的原因
–因此将使用下一个空闲内存地址。

TLAB变得满满的

可以想象,TLAB不是无限的,在某些时候它开始变满。 如果线程需要分配一个不适合当前TLAB的新对象(因为它几乎已满),则会发生两件事:

  • 线程获取新的TLAB
  • 该对象在TLAB之外分配

JVM根据几个参数决定将要发生的情况。 如果选择了第一个选项,则线程的当前TLAB将“退休”,并且分配将在新的TLAB中完成。 在第二种情况下,分配是在Eden的共享区域中完成的,这就是为什么需要某种同步的原因。 通常,同步是有代价的。

物体太大

默认情况下,将针对每个线程分别动态调整TLAB的大小。 根据Eden的大小,线程数及其分配率重新计算TLAB的大小。 更改它们可能会影响TLAB的规模-但是,由于分配率通常会有所不同,因此没有简单的公式可以解决。 当线程需要分配一个永远无法容纳在TLAB中的大对象(例如,大数组)时,它将在Eden的共享区域中分配,这又意味着同步。 这正是我的应用程序中正在发生的事情。 由于某些对象太大,因此它们从未在TLAB中分配。

在TLAB之外分配一些对象并不一定是一件坏事–这是在次要GC之前发生的典型情况。 问题是,与TLAB内部相比,TLAB外部有大量分配。 在这种情况下,有两个可用选项:

  • 缩小物体
  • 尝试调整TLAB尺寸

就我而言,手动调整TLAB大小不是最佳选择。 众所周知,只有很少的对象类型在TLAB之外分配。 通常,修复代码是最好的选择。 在我将对象显着缩小之后,它们已装入TLAB,并且TLAB内部分配给TLAB外部分配的比率恢复正常。

翻译自: https://www.javacodegeeks.com/2019/03/thread-local-allocation-buffers.html

本地线程分配缓冲

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值