90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(2)- TLAB预热[通俗易懂]

90% 的 Java 程序员都说不上来的为何 Java 代码越执行越快(2)- TLAB预热[通俗易懂]经常听到Java性能不如C/C++的言论,也经常听说Java程序需要预热,那么其中主要原因是啥呢?面试的时候谈到JVM,也有很多面试官喜欢问,为啥Java程序越执行越快呢?一般人都能回答上来,类加载,

经常听到 Java 性能不如 C/C++ 的言论,也经常听说 Java 程序需要预热,那么其中主要原因是啥呢

面试的时候谈到 JVM,也有很多面试官喜欢问,为啥 Java 程序越执行越快呢

一般人都能回答上来,类加载,缓存预热等等,但是深入下去,最重要的却没有答上来,今天本系列文章就来帮助大家理解这个问题的关键。本篇文章是 TLAB 预热。

TLAB(Thread Local Allocation Buffer)线程本地分配缓存区,这是一个线程专用的内存分配区域。

image

既然是一个内存分配区域,我们就先要搞清楚 Java 内存大概是如何分配的。

image

我们这里不考虑栈上分配,这些会在 JIT 的章节详细分析,我们这里考虑的是无法栈上分配需要共享的对象

对于 HotSpot JVM 实现,所有的 GC 算法的实现都是一种对于堆内存的管理,也就是都实现了一种堆的抽象,它们都实现了接口 CollectedHeap。当分配一个对象堆内存空间时,在 CollectedHeap 上首先都会检查是否启用了 TLAB,如果启用了,则会尝试 TLAB 分配;如果当前线程的 TLAB 大小足够,那么从线程当前的 TLAB 中分配;如果不够,但是当前 TLAB 剩余空间小于最大浪费空间限制(这是一个动态的值,我们后面会详细分析),则从堆上(一般是 Eden 区) 重新申请一个新的 TLAB 进行分配。否则,直接在 TLAB 外进行分配。TLAB 外的分配策略,不同的 GC 算法不同。例如G1:

  • 如果是 Humongous 对象(对象在超过 Region 一半大小的时候),直接在 Humongous 区域分配(老年代的连续区域)。
  • 根据 Mutator 状况在当前分配下标的 Region 内分配

这里,我们先只关心 TLAB 分配。 对于单线程应用,每次分配内存,会记录上次分配对象内存地址末尾的指针,之后分配对象会从这个指针开始检索分配。这个机制叫做 bump-the-pointer (撞针)。 对于多线程应用来说,内存分配需要考虑线程安全。最直接的想法就是通过全局锁,但是这个性能会很差。为了优化这个性能,我们考虑可以每个线程分配一个线程本地私有的内存池,然后采用 bump-the-pointer 机制进行内存分配。这个线程本地私有的内存池,就是 TLAB。只有 TLAB 满了,再去申请内存的时候,需要扩充 TLAB 或者使用新的 TLAB,这时候才需要锁。这样大大减少了锁使用。

TLAB 初始化

image

TLAB 分配

image

GC 时 TLAB 回收与重计算期望大小

image

为何 Java 代码越执行越快 – TLAB预热

根据之前的分析,每个线程的 TLAB 的大小,会根据线程分配的特性,不断变化并趋于稳定,大小主要是由分配比例 EMA 决定,但是这个采集是需要一定运行次数的。并且 EMA 的前 100 次采集默认是不够稳定的,所以 TLAB 大小也在程序一开始的时候变化频繁。当程序线程趋于稳定,运行一段时间后, 每个线程 TLAB 大小也会趋于稳定并且调整到最适合这个线程对象分配特性的大小。这样,就更接近最理想的只有 Eden 区满了才会 GC,所有 Eden 区的对象都是通过 TLAB 分配的高效分配情况。这就是 Java 代码越执行越快在 TLAB 方面的原因。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13091.html

(0)

相关推荐

  • Android基础:Fragment,看这篇就够了[亲测有效]

    Android基础:Fragment,看这篇就够了[亲测有效]下文中FragmentDemo的源代码地址:https://github.com/xiazdong/FragmentDemo基本概念Fragment,简称碎片,是Android3.0(API11)提出

    2023-08-10
    76
  • 找不到满足python(找不到满足jieba要求的版本)

    找不到满足python(找不到满足jieba要求的版本)电脑提示计算机丢失python34.dll:

    2023-11-29
    64
  • Python Widget Digit,打造高效数字化界面

    Python Widget Digit,打造高效数字化界面在现代社会,数字化已成为各行各业的趋势,需要我们处理数字化信息的频率越来越高。数字处理和显示是我们日常工作的重点,因此,有一个高效的数字化界面是非常重要的。Python Widget Digit能够帮助我们快速、轻松地构建一个高效的数字化界面。

    2024-04-03
    23
  • Python中strf time函数的格式指令

    Python中strf time函数的格式指令strftime()函数是Python中时间模块中的一个函数,可以将时间转换为字符串,而strptime(string,pattern)函数则是将字符串转换为时间类型。在Python中,strftime()函数常用于日期和时间的格式化,可以将日期和时间根据指定的格式指令转换为字符串。这篇文章将从多个方面涵盖strftime函数的格式指令,让读者更好地了解该函数的使用和功能。

    2024-02-11
    47
  • Oracle许可[亲测有效]

    Oracle许可[亲测有效]原因:因为甲方比较关心许可的一些问题,会经常问起,但是现场人员往往对许可的内容不太了解,这里基于网络搜索的内容进行统一梳理。因为内容大多来自于网络,如果文中有描述不当的,请大家指正!一、Oracle许

    2023-02-22
    104
  • 高可用的MongoDB集群[亲测有效]

    高可用的MongoDB集群[亲测有效]高可用的MongoDB集群 davidpp 0.9432015.09.22 23:48:04字数 2,254阅读 35,992 刚接触MongoDB,就要用到它的集群,只能硬着头皮短时间去看文档和尝…

    2023-03-26
    97
  • insert into 大量数据_insert select 太慢

    insert into 大量数据_insert select 太慢问题: MySQL 一次 insert 刷几次盘? 实验: 工具:pt-tools 先检查各个刷盘参数 2. 开启 pt-tools! 3. 在 MySQL 中,任意表插入一行 4. 观察 pt-i…

    2023-02-01
    138
  • Oracle中的函数——Ceil()[通俗易懂]

    Oracle中的函数——Ceil()[通俗易懂]Ceil(value) 函数返回大于等于指定值(value)的最小整数,取整,没有四舍五入这一说法 select Ceil(103.46) from dual 104 select Ceil(103.

    2023-02-20
    110

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注