jvm新生代调优

news2024/9/24 15:22:17

5-4 新生代调优

只有排除了自己代码的问题后,再进行内存调优,内存调优都是从新生代开始,因为新生代优化空间更大一些

  1. 新生代的特点
  1. 所有的new操作分配内存都是非常廉价的,非常快

TLABthread-local allocation buffer(可防止多个线程创建对象时的干扰)

每个线程都在Eden区中分配私有的区域,即TLAB;

当new一个对象时,首先检查TLAB缓冲区中是否有可用内存,如果有,会优先在这一块空间进行对象的分配。之所以这么做,因为对象的分配也有线程安全的问题:比如线程1需要使用这段内存,在分配还没结束的过程中,线程2也要用这段内存,就会造成内存的分配混乱。因此在做对象的内存分配时,也要做一个线程的并发安全的保护,当然这个操作是由jvm做的

能否减少线程之间对内存分配的并发冲突呢?可以使用TLAB线程分配局部缓冲区,他的作用就是使用自己私有的伊甸园内存进行对像的分配,这样的话,多个线程即使同时创建对象,也不会产生对内存占用的干扰。所以伊甸园区创建对象效率时非常高的

  1. 死亡对象回收零代价

学过的所有的垃圾回收器,在新生代垃圾回收采用的都是复制算法

复制算法是将伊甸园和from中存活对象复制到to中,然后释放伊甸园和from所有内存,所以说死亡对象回收零代价

  1. 大部分对象用过即死(朝生夕死)

新生代垃圾回收,绝大部分用过即死,只有少部分存货下来

  1. MInor GC 所用时间远小于Full GC

MinorGC的时间与FullGC的时间相差1-2个数量级别

  1. 新生代内存越大越好么?

-Xmn :设置新生代的初始和最大值

新生代进行调优,有的人认为就是将新生代进行调大,这是一个最有效的方式,但是也要注意新生代在调大的过程中存在的问题

Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery). GC is

performed in this region more often than in other regions. If the size for the young generation is

too small, then a lot of minor garbage collections are performed. If the size is too large, then only

full garbage collections are performed, which can take a long time to complete. Oracle

recommends that you keep the size for the young generation greater than 25% and less than

50% of the overall heap size.

  1. 太小

不是越大越好

新生代内存太小:频繁触发Minor GC,会STW,会使得吞吐量下降

如果设置小了,可用空间少,创建新对象时,一旦发现新生代空间不足,就会触发MinorGC,会产生STW,产生短暂的暂停

  1. 太大

新生代内存太大老年代内存占比有所降低堆空间一定前提下新生代认为空闲空间很多,新创建的对象不会触发GC。但是老年代的空间紧张,再触发垃圾回收,就是FullGC了。FullGC的STW要比MinorGC更长。如果新生代过大,引发的垃圾回收类型可能就是FullGC就需要占用更长的时间才能完成垃圾回收。会更频繁地触发Full GC。而且触发Minor GC时,清理新生代所花费的时间会更长

oracle给的建议是:堆的25%<新生代<堆的50%

  1. 吞吐量与新生代大小的关系

 

实际生产过程中,随着新生代的增加,吞吐量会有一个拐点,新生代如果设置的太小会引发的缺点,以及这个新生代如果。原因是新生代比较大,造成回收时间的变长

  1. 新生代大小

新生代内存设置为能容纳[并发量*(一次请求-响应所产生的对象)]的数据为宜

但是总的原则啊,我们还是要将新生代调的尽可能大。你刚才不是。还说啊,新生代的空间大了,那将来这个垃圾回收的时间变长了?但是我们刚才还有一个因素没有考虑进去。什么因素呢?就是新生代垃圾的回收都是复制算法。算法也是分成两个阶段,第1个阶段标记,第2个阶段呢去进行复制,那么这两个阶段哪个阶段花费的时间更多一些呢,其实是复制。因为复制牵扯到这个对象的占用内存块移动。另外呢你要更新对象引用的地址,这个速度相对更耗时一些。而新生代的对象,大家想想啊绝大部分都是朝生夕死的,也就是说最终只有少量的对象啊,只有少量的对象会存活下来的,所以既然是少量的对象存货,那它复制所占用的时间其实也是相对较短的,而标记时间,相对于复制时间来讲,显得不是那么重要,所以我们新生代调大的情况下。因为主要耗费的时间还是在复制上。即使增的很大效率也不会有特别明显的下降,这是对新生代大小设置的一个补充。

那究竟把它设成多大比较合适呢?我们的一个理想情况是,我的一个新生代能够容纳请求和响应过程中一次请求和响应过程中所产生的对象乘上并发量。举一个例子,比如说我一次请求响应的过程中呢,可能会创建很多新的对象,那这些新的对象加起来大约呢,比如说占到了512K的内存,那这是我的并发量呢,大概是1000。也就是,同一时刻,有1000个用户来访问我。这时候我的新生代,它的一个比较理想的内存就是。每一个请求响应乘以我的并发量,也就是512k×1000,大约是512M。为什么我们设成这么大就比较理想呢?这是因为你这一次请求响应的过程以后,其中大部分对象都会被回收。只要你这一次请求加上你的并发量所占用内存不超过我新生代的内存,它就不会触发。或较少的触发新生代的垃圾回收。这样就可以大约估算出新生代内存占用到底划分成多少比较合理。

  1. 幸存区大小

幸存区大到能保留【当前活跃对象+需要晋升对象】

新生代还有一块区域,我们称之为叫幸存区。幸存区呢,它的内存设置要遵从这么几个规则。

第1个呢,就是我们要考虑到幸存区啊,它也要足够的大,大到呢,能够保留当前的活跃对象和需要晋升的对象。这是什么意思呢?解释一下啊,幸存区中,你可以把它看成有两类对象:第1类对象呢,它是生命周期较短,也许下一次垃圾的时候就要把它回收掉了,但是由于现在还正在使用,它暂时不能回收,所以它就留在我们的幸存区中;另一类呢是他肯定将来会被晋升到老年的 ,因为大家都在用它,但是由于年龄还不够,所以暂时还存活在幸存区当中,没有被晋升。那幸存区中呢,就可以看成是这两类对象,存储的都是这两类对象。一类是马上就要被回收的一类是将来肯定要晋升的

那幸存区呢,你的大小就得大到把这两类对象都能够容纳。为什么这么说?这里要提到幸存区的一个晋升规则如果幸存区比较小,它就会由jvm动态的去调整你的这个晋升的阈值。也许你本来有一些对象,轮不到他晋升,它的寿命还不够,但是由于幸存区的内存太少,导致提前把一些对象晋升到老年代区。也许是刚才我们说的这种存活时间较短的对象,提前被晋升到了老年代,那这样有什么问题呢?或者说有什么缺点呢,就是如果你本来一个存活时间短的对象被晋升到了老年代,那就意味着,他得等到老年代内存不足时触发Full GC时才能把它当成垃圾进行回收。所以这就是变相的延长了这个对象的生存的时间。这是一个不太好的地方。我们最好能实现,就是这种存活时间短的,在下次新生代的垃圾回收里就把它回收掉了。真正需要,长时间存活的对象,我才把它晋升到老年代,这是一条规则。

  1. 晋升阈值

晋升阈值配置得当,让长时间存活对象尽快晋升

-XX:MaxTenuringThreshold=threshold  调整最大晋升阈值

-XX:+PrintTenuringDistribution

 

事物呢还是都有两面性,那么我们一方面希望的是存活时间短的对象让他留在幸存区,以便下一次垃圾回收能把它回收掉;而另一方面呢,我们又希望这个长时间存活的对象,他应该尽快的被晋升

为什么这么说呢,因为如果你是一个长时间存活的对象,你把它留在幸存区里,只能够浪费我们幸存区的这个内存,并且呢,因为我们的新生代垃圾回收都是复制算法,要把这个幸存区中的这些对象,下次存活了又要把它进行复制复制,从from复制到to,我们前面也说过,那么这个新生代复制算法主要的耗费时间就是在这个对象的复制上,如果有大量的这些长时间存活的对象,他们不能及早的晋升,那么他们就相当于留在这个幸存区,被复制来复制去,这样呢,对我的性能其实反而是一个负担。所以遇到这种情况呢就要设置一下它的晋升阈值,把晋升阈值调的比较小,让这些长时间存活的对象呢,能够尽快的晋升到老年代区。这个参数:-XX:MaxTenuringThreshold=threshold  可以调整最大晋升阈值。

有的时候我们还需要把它晋升的一些详细信息显示出来,便于我去判断到底应该把晋升阈值设置为多少更为比较合适,相关的参数是下面这个参数:-XX:+PrintTenuringDistribution 这个参数呢,带上以后它就会在每次垃圾回收时把survival幸存区中的这些存活对象、详情显示出来。第一列,就是它的一个对象的年龄我们可以从这个事例中看到,年龄为1的,是刚逃过一次MinorGCC的这个对象,它占用的空间大小是多少;年龄2的对象在这个幸存区中的对象占用了多少的空间;为3的占用空间是多少这是年龄为1、2、3的对象各自占用空间数,后面是他们的累计总和数——空间占用的累计总和,比如说12加起来是3058888,123加起来是31784800。通过每次把这个幸存区中不同年龄的对象它所占用的空间打印,我们可以更细致的去决定到底把最大的晋升阈值调成多少比较合适,让那些长时间存在的影响能够尽早的晋升。这就是对新生代内存调优的一个说明。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/739092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

go-zero微服务实战——服务构建

目录介绍 接上一节go-zero微服务实战——基本环境搭建。搭建好了微服务的基本环境&#xff0c;开始构建整个微服务体系了&#xff0c;将其他服务也搭建起来。 order的目录结构&#xff0c;如下 根目录 api服务rpc服务自定义逻辑层logic自定义参数层models自定义工具层util …

RAR Extractor Max - Unzip for Mac(简单易用的压缩软件)

RAR Extractor Max是一个软件应用程序&#xff0c;旨在从RAR档案中提取文件。RAR是一个流行的归档文件解压软件&#xff0c;广泛用于压缩和归档文件。RAR Extractor Max是专门为处理RAR文件而设计的&#xff0c;对于任何经常处理这种文件格式的人来说&#xff0c;这是一个有用的…

【运维工程师学习四】Web服务之Apache

【运维工程师学习四】Web服务之Apache 1、查询、安装apacherpm命令使用 2、验证httpd是否启动成功&#xff08;1&#xff09;、查看是否有httpd的进程&#xff08;2&#xff09;、查看是否有80端口在监听中&#xff08;3&#xff09;、CentOS7默认不带netstat命令&#xff0c;通…

自定义TagViewGroup

来看看如何实现最最基本的TagGroupView&#xff0c;该视图作为ViewGroup的作用是实现其中的子视图的自动换行&#xff0c;保证子视图能够按照在xml中传入的顺序来相对合理地显示到界面上。 注意&#xff1a;其实在Android技术已经非常完善的当下&#xff0c;其实我们已经不怎么…

【k8s】k8s的yaml文件解释,如何部署一个java.jar包

前言&#xff1a; k8s的yaml文件解释&#xff0c;如何部署一个java,jar包 YAML语法格式&#xff1a; 大小写敏感&#xff1b;使用缩进表示层级关系&#xff1b;不支持Tab键制表符缩进&#xff0c;只使用空格缩进&#xff1b;缩进的空格数目不重要&#xff0c;只要相同层级的元…

Imx6ull linux 设备树

一 linux设备树简介 1.1 linux设备树 Linux设备树是一种用于描述硬件设备信息的数据结构&#xff0c;它在Linux内核中发挥着越来越重要的作用 在系统上电后&#xff0c;BootLoader会将设备树传递给Linux内核&#xff0c;内核根据识别的树信息展开为platform_device、spi_dev…

如何用爬虫实现GPT功能

如何用爬虫实现GPT功能&#xff1f; GPT&#xff08;Generative Pre-trained Transformer&#xff09;和爬虫是两个完全不同的概念和技术。GPT是一种基于Transformer模型的自然语言处理模型&#xff0c;用于生成文本&#xff0c;而爬虫是一种用于从互联网上收集数据的技术。 …

贝叶斯 A/B 测试解释与Python实现

一、说明 A / B测试在各个行业中有许多应用。从试图确定最佳市场群体到医疗药物测试&#xff0c;它具有各种应用&#xff0c;并允许企业根据结果做出决策。有两种常见的A/B检验方法&#xff0c;频率主义方法和贝叶斯方法&#xff0c;两者都是从假设检验的基础出发的。在本文中&…

819. 递归求阶乘

链接&#xff1a; 819.递归求阶乘 题目&#xff1a; 请使用递归的方式求 nn 的阶乘。 输入格式 共一行&#xff0c;包含一个整数 nn。 输出格式 共一行&#xff0c;包含一个整数&#xff0c;表示 nn 的阶乘的值。 数据范围 1≤n≤101≤n≤10 输入样例&#xff1a; 3输出样例&am…

【Linux】查看系统各种信息的常用命令 (CPU、内存、进程、网口、磁盘、硬件、等等)

Linux是一种开源的类Unix操作系统&#xff0c;它有很多不同的发行版&#xff0c;如Ubuntu、CentOS、Debian等。Linux系统提供了很多命令行工具&#xff0c;可以让用户方便地查看和管理系统的各种信息&#xff0c;如硬件配置、内存使用、进程状态、网络连接等。本文将介绍一些常…

解决IDEA项目external libraries依赖包消失的问题

有时候电脑重启后&#xff0c;再打开IDEA上的项目时会出现external libraries目录下的依赖包都消失了的情况&#xff0c;只剩下了一个JDK的包 网上说可以通过刷新IDEA的缓存解决&#xff0c;但我试了没有效果&#xff0c;最后使用如下办法解决&#xff1a; 1.删除项目目录下的…

python接口自动化(二十五)--unittest断言——下(详解)

简介 本篇还是回归到我们最初始的话题&#xff0c;想必大家都忘记了&#xff0c;没关系看这里&#xff1a;传送门 没错最初的话题就是登录&#xff0c;由于博客园的登录机制改变了&#xff0c;本篇以我找到的开源免费的登录API为案例&#xff0c;结合 unittest 框架写 2 个用例…

MySQL原理探索——26 备库为什么会延迟好几个小时

在上一篇文章中&#xff0c;介绍了几种可能导致备库延迟的原因。你会发现&#xff0c;这些场景里&#xff0c;不论是偶发性的查询压力&#xff0c;还是备份&#xff0c;对备库延迟的影响一般是分钟级的&#xff0c;而且在备库恢复正常以后都能够追上来。 但是&#xff0c;如果备…

nvm的安装与使用5分钟极速上手

nvm的安装与使用5分钟极速上手 下载 nvm 并安装 nvm官网下载地址推荐下载 nvm-setup.zip 这一个&#xff0c;nvm-noinstall.zip下载之后不用安装&#xff0c;但是得自己配置setting.txt文件&#xff0c;以及环境变量&#xff0c;过于麻烦。nvm-setup.zip 会直接帮我们把环境变…

开篇(变量、运算符、进制)

一、Java简介 JDK&#xff08;JRE&#xff08;JVM & API&#xff09;、Java language&#xff08;tools & APIs&#xff09;&#xff09;&#xff1b;java源文件 → javac的编译 → class类&#xff08;会生成一个或多个class文件&#xff09;&#xff1b; * 使用 jav…

什么是Qt Widgets?一组创建经典桌面应用UI的界面组件!

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 Qt Widgets模块提供…

QGIS 根据点位批量出图

背景 在工作中&#xff0c;当有大量项目点位需要结合地图介绍时&#xff0c;则需要批量截图。于是有了今天的教程。 一 工具及材料准备 QGIS 插件 QuickMapServices 点位集合 CSV文件 其他图层文件 二 导入图层 这里根据实际需要导入自己对应格式的就好。 图层-添加…

计算机网络地址

1、ipv4地址 2、网络地址转换 3、子网划分和主机号

Spring MVC 注解实现

注解描述 注解描述Controller用于标记在一个类上&#xff0c;使用它标记的类就是一个SpringMVC Controller 对象&#xff0c;分发处理器将会扫描使用了该注解的类的方法&#xff0c;并检测该方法是否使用了RequestMapping 注解。Controller 只是定义了一个控制器类&#xff0c…

第七章 环境软件的安装

1、nodeJS安装 node -v node版本 安装多个node版本 pnpm i nvm -g nvm -v nvm ls 查看当前安装的版本 nvm install 18.7.0 安装指定的版本 nvm use 18.6.0 切换到别的版本 安装pnpm npm i pnpm -g pnpm -v 安装VSCode 官网直接下载 安装好后 需要配置 按住 CMD +…