Java性能权威指南-总结6

news2024/11/24 12:02:20

Java性能权威指南-总结6

  • 垃圾收集入门
    • 垃圾收集概述
      • GC算法
      • 选择GC算法

垃圾收集入门

垃圾收集概述

GC算法

JVM提供了以下四种不同的垃圾收集算法:

  1. Serial垃圾收集器

Serial垃圾收集器是四种垃圾收集器中最简单的一种。如果应用运行在Client型虚拟机(Windows平台上的32位JVM或者是运行在单处理器机器上的JVM)上,这也是默认的垃圾收集器。

Serial收集器使用单线程清理堆的内容。使用Serial收集器,无论是进行Minor GC还是Full GC,清理堆空间时,所有的应用线程都会被暂停。进行Full GC时,它还会对老年代空间的对象进行压缩整理。通过-XX:+UseSerialGC标志可以启用Serial收集器(大多数情况下,如果可以使用这个标志,默认就会开启)。注意,跟大多数的JVM标志不同,关闭Serial收集器不能简单地将加号符变成减号符(譬如,使用-XX:-UseSerialGC)。在Serial收集器作为默认收集器的系统上,如果需要关闭Serial收集器,可以通过指定另一种垃圾收集器来实现。

  1. Throughput垃圾收集器

Throughput收集器是Server级虚拟机(多CPU的Unix机器以及任何64位虚拟机)的默认收集器。
Throughput收集器使用多线程回收新生代空间,Minor GC的速度比使用Serial收集器快得多。处理老年代时Throughput收集器也能使用多线程方式。这已经是JDK 7u4及之后的版本的默认行为,对于之前老版本的JDK7虚拟机,通过-XX:+UseParalleloldGc标志可以开启这个功能。由于Throughput收集器使用多线程,Throughput收集器也常常被称为Parallel收集器。 Throughput收集器在Minor GC和Full GC时会暂停所有的应用线程,同时在Full GC过程中会对老年代空间进行压缩整理。由于在大多数适用的场景,它已经是默认的收集器,所以基本上不需要显式地启用它。如果需要,可以使用-XX:+UseParallelGC-XX:+UseParalleloldGc标志启用Throughput收集器。

  1. CMS收集器

CMS收集器设计的初衷是为了消除Throughput收集器和Serial收集器Full GC周期中的长时间停顿。CMS收集器在Minor GC时会暂停所有的应用线程,并以多线程的方式进行垃圾回收。然而,这其中最显著的不同是,CMS不再使用Throughput的收集算法(-XX:+UseParallelGC),改用新的算法来收集新生代对象(使用-XX:+UseParNewGC标志)。

CMS收集器在Full GC时不再暂停应用线程,而是使用若干个后台线程定期地对老年代空间进行扫描,及时回收其中不再使用的对象。 这种算法帮助CMS成为一个低延迟的收集器:应用线程只在Minor GC以及后台线程扫描老年代时发生极其短暂的停顿。应用程序线程停顿的总时长与使用Throughput收集器比起来短得多。

额外付出的代价是更高的CPU使用:必须有足够的CPU资源用于运行后台的垃圾收集线程,在应用程序线程运行的同时扫描堆的使用情况。除此之外,后台线程不再进行任何压缩整理的工作,这意味着堆会逐渐变得碎片化。如果CMS的后台线程无法获得完成他们任务所需的CPU资源,或者如果堆变得过度碎片化以至于无法找到连续空间分配对象,CMS就蜕化到Serial收集器的行为:暂停所有应用线程,使用单线程回收、整理老年代空间。 这之后又恢复到并发运行,再次启动后台线程(直到下一次堆变得过度碎片化)。通过-XX:+UseConcMarkSweepGC-XX:+UseParNewGC标志(默认情况下,这两个标志都是禁用的)可以启用CMS垃圾收集器。

  1. G1垃圾收集器

G1垃圾收集器(或者垃圾优先收集器)的设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。G1收集算法将堆划分为若干个区域(Region),不过它依旧属于分代收集器。这些区域中的一部分包含新生代,新生代的垃圾收集仍然采用暂停所有应用线程的方式,将存活对象移动到老年代或者Survivor空间。同其他的收集算法一样,这些操作也利用多线程的方式完成。
G1收集器属于Concurrent收集器:老年代的垃圾收集工作由后台线程完成,大多数的工作不需要暂停应用线程。由于老年代被划分到不同的区域,G1收集器通过将对象从一个区域复制到另一个区域,完成对象的清理工作,这也意味着在正常的处理过程中,G1收集器实现了堆的压缩整理(至少是部分的整理)。因此,使用G1收集器的堆不大容易发生碎片化——虽然这种问题无法避免。

同CMS收集器一样,避免Full GC的代价是消耗额外的CPU周期:负责垃圾收集的多个后台线程必须能在应用线程运行的同时获得足够的CPU运行周期。通过标志-XX:+UseG1GC(默认值是关闭的)可以启动G1垃圾收集器。

触发及禁用显式的垃圾收集
通常情况下垃圾收集是由JVM在需要的时候触发:新生代用尽时会触发Minor GC,老年代用尽时会触发Full GC,或者堆空间即将填满时会触发Concurrent垃圾收集(如果情况需要)。

Java也提供了一种机制让应用程序强制进行GC:这就是System.gc()方法。通常情况下,试图通过调用这个方法显式触发GC都不是个好主意。调用这个方法会触发FullGC(即使JVM使用CMS或者G1垃圾收集器),应用程序线程会因此而停顿相当长的一段时间。同时,调用这个方法也不会让应用程序更高效,它会让GC更早地开始,但那实际只是将性能的影响往后推迟而已。

任何原则都有例外,尤其是在做性能监控或者基准测试时。运行少量的代码进行基准测试时,为了更快地预热JVM,在测量周期之前强制进行一次GC还是有意义的。类似的情况还包括在进行堆分析时,通常在获取堆转储之前,强制进行一次Full GC是一个不错的主意。虽然大多数抓取堆转储的方法都能进行Full GC,也存在其他的方法可以强制进行Full GC:你可以通过执行jcmd<进程号>GC.run,或者使用jconsole连接到JVM在内存面板上单击“进行GC”按钮。

另一个例外是RMI,作为它分布式垃圾收集器的一部分,每隔一小时它会调用System.gc()一次。这里的调用时间可以通过系统属性中的-Dsun.rmi.dgc.server.gcInterval=N.Dsun.rmi.dgc.cli ent.gcInterval=N进行修改。N值的单位以毫秒记,在Java7(该值与之前的版本亦不相同)中的默认值为3600000(即一个小时)。

如果你运行的程序调用的第三方代码中错误地调用了System.gc()方法,可以通过JVM参数-XX:+DisableExplicitGC显式地禁止这种类型的GC;默认情况下该标志是关闭的。

快速小结

  1. 这四种垃圾收集算法分别采用了的不同的方法来缓解GC对应用程序的影响。
  2. 2.Serial收集器常用于仅有单CPU可用以及当其他程序会干扰GC的情况(通常是默认值)。
  3. 3.Throughput收集器在其他的虚拟机上是默认值,它能最大化应用程序的总吞吐量,但是有些操作可能遭遇较长的停顿。
  4. 4.CMS收集器能够在应用线程运行的同时并行地对老年代的垃圾进行收集。如果CPU的计算能力足以支撑后台垃圾收集线程的运行,该算法能避免应用程序发生Full
    GC。
  5. G1收集器也能在应用线程运行的同时并发地对老年代的垃圾进行收集,在某种程度上能够减少发生Full GC的风险。G1的设计理念使得它比CMS更不容易遭遇Full GC。

选择GC算法

GC算法的选择一方面取决于应用程序的特征,另一方面取决于应用的性能目标。
Serial收集器最适用于应用程序的内存使用少于100MB的场景。 这种情况下应用程序只需要很小的堆,无论是Throughput收集器的并行收集,还是CMS收集器或G1收集器的后台收集都发挥不了太大的作用。

这个Sizing准则也限制了Serial收集器的使用范畴。大多数的程序需要在Throughput和Concurrent收集器之间做出抉择;而选择的依据大多数情况下是由应用程序的性能目标所决定的m, 不同应用在耗时、吞吐量、或者平均(或者总量90%的)响应时间上的要求迥异。

  1. GC算法及批量任务

对批量任务而言,Throughput收集器所引入的停顿,尤其是FulI GC的停顿是主要的顾虑。每个任务的执行都会为总的执行时间增加一部分的延迟时间(elapse time)。如果每次Full GC耗时0.5秒,程序5分钟的运行时间内要进行20个这样的周期,那么性能的损耗就高达3.4%:如果没有这些停顿,程序可以在290秒而不是300秒内完成运行。

如果有额外的CPU处理能力(这很可能是个问题),那么使用Concurrent收集器将极大地提升应用程序的性能。 这里的关键在于我们能否提供足够的CPU给Concurrent收集器的线程进行后台的处理工作。举个简单的例子:一个单CPU的机器上,单线程的应用程序已经消耗了100%的CPU资源。该应用程序使用Throughput收集器运行时,GC间歇性地发生,导致应用程序线程出现停顿。同样的程序,如果切换到Concurrent收集器,操作系统一会在CPU上运行应用程序线程,一会儿运行GC的后台线程。最终的结果是一样的:操作系统运行其他线程时,应用程序线程依然会发生停顿(不过有可能是更短时间的停顿)。

这个原则同样适用于通用情况,即多个应用程序线程、多个后台GC线程运行于多CPU的系统上。如果操作系统无法在同时运行所有应用程序线程和GC后台线程,那么对CPU的竞争就会反映到应用程序线程的停顿上。
在这里插入图片描述

上面的图片展示了这个取舍是如何工作的。计算股票数据的批量应用已经运行于特定的模式,它们会将结果集保持在内存中数分钟(目的是填满整个堆);测试分别使用了CMS和Throughput垃圾收集算法。

快速小结

  1. 使用Throughput收集器处理应用程序线程的批量任务能最大程度地利用CPU的处理能力,通常能获得更好的性能。
  2. 如果批量任务并没有使用机器上所有可用的CPU资源,那么切换到Concurrent收集器往往能取得更好的性能。
  3. 算法和吞吐量测试 测试度量的目标是吞吐量时,选择GC算法的最基本的取舍跟批量任务一样,但是停顿所产生的影响却是大相径庭。CPU仍然是影响总体性能非常重要的一环

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

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

相关文章

【TaskMatrix.AI - Visual ChatGPT】连接超大模型和超多API来完成任务

Github项目地址&#xff1a;https://github.com/microsoft/TaskMatrix 目前大规模预训练模型&#xff08;比如ChatGPT&#xff09;已经能够完成多个任务&#xff0c;例如 提供强大的对话功能&#xff0c;in-context learning能力和代码生成能力生成高层次的解决问题框架 然而…

Vue.js 比较重要知识点总结四

概述 ref toRef toRefs进阶&#xff0c;深入理解vue3 setupVue3为何比Vue2快&#xff1f;怎样理解 Vue 的单向数据流&#xff1f;Vue 中事件绑定原理vue3 mitt 使用 ref toRef toRefs进阶&#xff0c;深入理解 为何需要ref&#xff1f; 返回值类型&#xff0c;会丢失响应式se…

【常用设计模式】待补充

Github仓库地址 概述 23中设计模型分为常见的三大类&#xff1a;创建型模式、结构型模式和行为型模式 创建型模式 简单工厂模式 描述 简单工厂模式不是23中设计模式中的。简单工厂模式不直接向客户端暴露对象创建的细节&#xff0c;而是通过一个工厂类来负责创建产品类的实…

12.MSP432E4 Keil烧录报错Error Flash Download failed - Cortex-M4

一、简介 前段时间琢磨了一块新板子&#xff0c;ESP432E401Y。 遇到一个问题&#xff0c;简单记录一下&#xff0c;问题是在keil中正常烧录程序后&#xff0c;在CCS下也烧录了一次程序&#xff0c;然后就一直无法再到keil中烧录&#xff0c;但是CCS一直是正常烧录的。keil报错…

Spark集群搭建

系列文章目录 Ubuntu常见基本问题 Hadoop3.1.3安装&#xff08;单机、伪分布&#xff09; Hadoop集群搭建 HBase2.2.2安装&#xff08;单机、伪分布&#xff09; Zookeeper集群搭建 HBase集群搭建 Spark安装和编程实践&#xff08;Spark2.4.0&#xff09; Spark集群搭建 文章目…

linux开发:linux最大线程数分析

linux最大线程数分为&#xff0c;进程最大线程数&#xff0c;用户最大进程数&#xff0c; 整个系统已用的线程或进程数。 我们可以用下面命令进行查询这三个进程数。 linux系统可生成最大线程数可以用这个命令查询 cat /proc/sys/kernel/threads-max 进程最大线程数查询方式 ps…

家用儿童帆布床出口欧盟CE认证EN716测试

1.标准适用范围 该标准规定了内部长度大于900mm但不超过1400mm的家用童床的安全要求。该安全要求适用于完全组装完毕待用的童床。可以转换成其它产品的童床&#xff08;如&#xff1a;可变产品、游戏床&#xff09;转换后应该符合相关欧洲标准。该标准不适用于提篮、婴儿床和摇…

hacknet攻略(更新中)

序章 然后点自己的电脑&#xff0c;再点一下SCAN(扫描可用主机)&#xff0c;再点断开 然后点蓝色的电脑&#xff0c;是连接的意思 点中间Probe系统图标&#xff0c;看开放端口数 若端口数为0可以使用porthakc命令直接黑入系统 几个会用到的命令cd, rm * ,dc关闭连接&…

Unity制作二次元卡通渲染角色材质——4 、内外描边和细节添加

Unity制作二次元材质角色 回到目录 大家好&#xff0c;我是阿赵。 这里继续讲二次元角色材质。这次打算讲一下描边和细节的添加。 一、外描边 外描边的做法也不止一种&#xff0c;比如后处理方法的偏导数ddx/ddy之类的&#xff0c;也能整个屏幕的求出边缘。但一般来说单模型渲…

MySQL数据库学习笔记(九)实验课六之触发器和存储过程

没想到这就是最后一次实验了。 一点知识&#xff1a; 道具 – delimiter / DELIMITER 这是用于指定语句分隔符的特殊命令 默认情况下&#xff0c;MySQL使用分号&#xff08;;&#xff09;作为语句的结束符。然而&#xff0c;当我们需要定义存储过程、触发器或函数等包含多条S…

51智能小车-串口控制、循迹、避障

目录 1.串口控制小车 2.循迹小车 3.避障小车 1.串口控制小车 L9110s概述 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;但是不对&#xff0c;根据下节课实际调试 IA1输入高电平&#xff0c;IA1输入低电平&#xff0c;【OA1 OB1】电机…

总结890

学习目标&#xff1a; 月目标&#xff1a;6月&#xff08;线性代数强化9讲2遍&#xff0c;背诵15篇短文&#xff0c;考研核心词过三遍&#xff09; 周目标&#xff1a;线性代数强化3讲&#xff0c;英语背3篇文章并回诵&#xff0c;检测 每日必复习&#xff08;5分钟&#xff…

STM32开发——简介、开发环境(Keil5、CubeMX)、HAL库

目录 1.简介-初识STM32 2.开发环境 2.1使用Keil5 2.2使用STM32CubeMX 3.标准库与HAL库区别 4.推挽输出与开漏输出 1.简介-初识STM32 什么是单片机&#xff1f; 单片机&#xff08;Single-Chip Microcomputer&#xff09;是一种集成电路芯片&#xff0c;把具有数据处理能…

kafka部分面试常见问题及其解答(接上)

16. kafka创建Topic时如何将分区分配给各Broker 副本因子不能大于 Broker 的个数&#xff1b;第1个分区&#xff08;partition_0&#xff09;的第1个副本放置位置是随机从brokerList选择的&#xff1b;其他分区的第一个副本放置位置相对于partition_0依次往后移。 如果我们有5…

vue 3 第三十二章:状态管理(Pinia状态持久化)

Pinia 的状态持久化 在实际开发中&#xff0c;我们通常需要对状态进行持久化或缓存&#xff0c;以便在应用程序重新加载或离线时仍然能够访问数据。在 Pinia 中&#xff0c;我们可以使用插件来实现状态的持久化和数据缓存。 Pinia 提供了一个名为pinia-plugin-persist的插件&…

Linux - 文件操作和系统接口

​​​​​​​ 感谢各位 点赞 收藏 评论 三连支持 本文章收录于专栏【Linux系统编程】 ❀希望能对大家有所帮助❀ 本文章由 风君子吖 原创 ​​​​​​​ ​​​​​​​ ​​​​​​​ ​ 前言 对于文件操作&#xff0c;不知大家是否有过接…

永恒之黑漏洞复现

一、实验环境搭建 系统镜像&#xff1a; ed2k://|file|cn_windows_10_consumer_editions_version_1903_x64_dvd_8f05241d.iso|4905476096|F28FDC23DA34D55BA466BFD6E91DD311|/ 建议使用迅雷下载,安装版本选win10专业版 安装完后记得一定要关闭defender&#xff0c;防火墙&…

配置主机加入已有 tinc 集群简明过程

文章目录 Cent OS服务器安装tinc配置文件过程中使用到的一些Linux命令小记 启动tinc开放端口 Windows主机参考资料 本文的主要内容是如何将主机加入已有的 tinc 集群。 Cent OS服务器 安装tinc yum install tinc如果不先 su 到 root 账户的话&#xff0c;可能会无法安装。 因…

Python模块os 操作系统

目录 1. 系统类 --------------------- 解释器 --------------------- system 执行系统命令 wait 等待任意子进程 waitpid 等待指定的子进程 kill 指定杀死进程 abort 立即中止解释器 pipe 管道操作 --------------------- 随机字符 --------------------- urandom …

KMeans+DBSCAN密度聚类+层次聚类的使用(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…