首页 > 编程语言 >Java 性能调优:优化 GC 线程设置

Java 性能调优:优化 GC 线程设置

时间:2024-09-17 19:22:28浏览次数:11  
标签:Java 应用程序 调优 GC 回收 JVM 线程 CPU

垃圾回收器使用一组称为 GC 线程的线程来执行回收工作。有时 JVM 可能会分配过多或过少的 GC 线程。本文将讨论 JVM 为什么会出现这种情况、其影响以及可能的解决方案。

1 咋查找应用程序的 GC 线程数量

进行线程转储分析来确定应用程序的 GC 线程数量:

  1. 从生产服务器捕获thread dump
  2. 使用thread dump分析工具进行分析
  3. 立即显示 GC 线程数量,如图

Java 性能调优:优化 GC 线程设置_应用程序

还可通过 JMX(Java Management Extensions)或VisualVM、JConsole 等查看 GC 线程数量。

2 咋设置 GC 线程数量?

JVM 参数手动调整 GC 线程数:

  • -XX:ParallelGCThreads=n:设置垃圾回收器并行阶段使用的线程数量
  • -XX:Cnotallow=n:控制垃圾回收器并发阶段使用的线程数量

注意这些参数适用于并行垃圾回收器(如 ParallelGC 和 ParallelOldGC)和并发垃圾回收器(如 G1GC)。

3 默认 GC 线程数量多少?

根据服务器或容器中的 CPU 数量自动计算。

  • -XX:ParallelGCThreads 默认值:在 Linux/x86 系统上,默认值公式:
if (处理器数量 <=8) {   
   返回处理器数量; 
} else {  
  返回 8 + (处理器数量 - 8) * (5/8); 
}

因此,如果 JVM 运行在拥有 32 个处理器的服务器上,那么 ParallelGCThread 的值将是 23。

  • -XX:ConcGCThreads 默认值:公式:
max((ParallelGCThreads+2)/4, 1)

因此,如果 JVM 运行在 32 个处理器的服务器上:

  • ParallelGCThread 的值将是 23(即 8 + (32 – 8) * (5/8))
  • ConcGCThreads 的值将是 6(即 max(25/4, 1))

4 JVM 会分配过多的 GC 线程吗?

JVM 可能在你不知情下分配过多 GC 线程。因为默认 GC 线程数量是根据服务器或容器中的 CPU 数量自动确定。

如在拥有 128 个 CPU 机器,JVM 可能会为垃圾回收的并行阶段分配大约 80 个线程,并为并发阶段分配大约 20 个线程,总计 100 个 GC 线程。

如你在这台 128 CPU 的机器上运行多个 JVM,每个 JVM 可能会分配大约 100 个 GC 线程。这会导致资源的过度使用,因为所有这些线程都在争夺相同的 CPU 资源。这种情况在容器化环境中特别常见,因为多个应用程序共享相同的 CPU 核心,导致 JVM 分配的 GC 线程超过所需数量,从而降低整体性能。

容器化环境

JVM 可能根据容器分配的 CPU 资源来计算 GC 线程数量,而非物理机器的 CPU 数量。这可能导致在共享 CPU 资源的容器环境中分配过多的 GC 线程。

5 过多GC线程也是问题?

虽然 GC 线程对高效的内存管理非常重要,但过多 GC 线程可能会导致 Java 应用程序性能问题。

上下文切换增加

当 GC 线程过多时,操作系统需要频繁地在这些线程之间切换,导致上下文切换的开销增加,更多的 CPU 时间花在管理线程上,而不是执行应用程序代码,结果应用程序可能会明显变慢。

CPU 开销增加

每个 GC 线程都会消耗 CPU 资源,过多的线程同时活跃时,它们会争夺 CPU 时间,减少应用程序的主要任务的处理能力,特别是在 CPU 资源有限的情况下。

内存争用

过多的 GC 线程会增加内存资源争用,多个线程同时访问和修改内存会导致锁争用,从而进一步降低应用程序性能。

GC 暂停时间增加,吞吐量下降

过多的 GC 线程会使垃圾回收过程低效,导致更长的 GC 暂停时间,应用程序会被暂时中断,延长的暂停时间可能会造成明显的延迟或卡顿。此外,更多的时间花在垃圾回收上而不是处理请求,应用程序的整体吞吐量会下降,从而影响其在高负载下的扩展性和性能。

延迟增加

由于过多线程导致 GC 活动增加,响应用户请求或处理任务的延迟也会增加,这对需要低延迟的应用程序来说尤其严重,例如实时系统或高频交易平台。

边际效益递减

增加 GC 线程到一定程度后,并不会继续提高性能,反而会出现边际效益递减,管理这些线程的开销超过了更快垃圾回收的好处,这会导致应用性能下降。

6 过少GC线程还是问题?

过少的 GC 线程同样会给 Java 应用程序带来问题。原因如下:

  1. 垃圾回收时间延长:GC 线程过少时,垃圾回收所需时间变长,线程少,处理时间长,GC 暂停时间也随之延长。
  2. 应用程序延迟增加:垃圾回收时间过长会增加应用程序的延迟,特别是对于需要低延迟的应用程序,用户可能会感到应用程序无响应。
  3. 吞吐量降低:GC 线程数量不足会导致垃圾回收器工作效率降低,进而影响整体吞吐量,应用程序每秒处理的请求或事务变少,影响其扩展能力。
  4. CPU 利用率低下:线程过少时,CPU 核心可能无法充分利用,部分核心闲置,部分核心负载过重,资源利用率不均衡。
  5. 增加OOM和内存泄漏风险:GC 线程过少可能导致垃圾回收器无法跟上内存分配的速度,回收不及时,可能出现OOM,甚至导致内存泄漏和崩溃。

7 优化 GC 线程数的解决方案

若应用程序因 GC 线程数量不当导致性能问题,可通过 JVM 参数手动调整 GC 线程数:

  • -XX:ParallelGCThreads=n
  • -XX:Cnotallow=n

在生产环境中应用这些更改前,先研究应用程序的 GC 行为,收集并分析 GC 日志。根据分析结果,判断当前线程设置是否导致性能瓶颈,然后进行相应调整。

务必在受控环境中测试这些更改,以确保它们的确能改善性能,然后再应用于生产环境。调整 GC 线程数量时,应结合应用程序的实际工作负载、内存使用情况和硬件配置进行综合考虑。此外,可以使用工具如 GCViewer 来分析 GC 日志,以更好地理解 GC 行为并进行优化。

8 总结

平衡 GC 线程数量对 Java 应用程序的平稳运行至关重要。通过仔细监控和调整这些设置,可以避免潜在的性能问题,并保持应用程序的高效运行。

标签:Java,应用程序,调优,GC,回收,JVM,线程,CPU
From: https://blog.51cto.com/JavaEdge/12038162

相关文章

  • Java基础语法-标识符
    标识符关键字Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符标识符注意点所有的标识符都应该以字母(A-Z或者a-z),美元($),或者下划线(_)开始首字符之后可以是字母(A-Z或者a-z),美元($),下划线(_)或数字的任何字符组合不能使用关键字作为......
  • day03 - Java集合和常用类
    第一章Collection集合1.Collection概述集合:java中提供的一种容器,可以用来存储多个数据集合和数组既然都是容器,它们有啥区别呢?数组的长度是固定的。集合的长度是不固定的。集合可以随时增加元素,其大小也随之增加数组中存储的是同一类型的元素,可以存储基本数据类型值。......
  • java线程池编程示例
    程序功能这段代码展示了如何使用Java线程池来并发执行多个任务。通过创建一个固定大小为3的线程池,程序提交了5个任务,并让线程池中的线程并发处理这些任务。每个任务模拟了一个耗时操作,最后程序等待所有任务完成后关闭线程池。代码importjava.util.concurrent.Ex......
  • 如何打造动漫天堂?宇宙动漫网站设计与实现,Java SpringBoot Vue技术揭秘
    ✍✍计算机毕业编程指导师**⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!⚡⚡Java、Python、微信小程序、大数据实战项目集⚡⚡文末......
  • 3.Java高级编程实用类介绍(一)
    三、Java高级编程实用类介绍(一)文章目录三、Java高级编程实用类介绍(一)一、枚举类型二、包装类三、Math一、枚举类型使用enum进行定义publicenum枚举名字{值1,值2....}二、包装类每个基本类型在java.lang包中都有一个相应的包装类 /* *new包......
  • Vue学习笔记3:对比纯JavaScript和Vue实现数据更新的实时视图显示
    0前言在页面中,要实现数据更新的视图实时显示,纯JavaScrip需要手动编写代码来处理数据和视图之间的更新。而Vue提供了数据绑定的能力,使得数据和视图保持同步。我们通过一个实例来体验两者的差别。我们设计一个页面,在页面里提供一个文本框,用户可以在文本框输入内容,然后我们在文本框下......
  • 4.Java高级编程实用类介绍(二)
    四、Java高级编程实用类介绍(二)文章目录四、Java高级编程实用类介绍(二)一、Random类二、字符串常用方法一、Random类//获得随机数Randomrand=newRand();System.out.println(rand.nextInt(100));//获得20-35的随机数Sytem.out.println(rand.nextInt......
  • Java基础:Api 文档注释,字符串种类,String字符串创建,特点及常用方法
    #1API文档注释*有三种注释 1.`单行注释 //` 2.`多行注释/*  */` 3.`文档注释/** */`*文档注释一般建议写在类,属性和方法上。jdk提供了javadoc.exe工具 对程序的所有类及属性和方法生成一个说明文档 :API文档*API:ApplicationProgramInte......
  • Java 性能调优:优化 GC 线程设置
    垃圾回收器使用一组称为GC线程的线程来执行回收工作。有时JVM可能会分配过多或过少的GC线程。本文将讨论JVM为什么会出现这种情况、其影响以及可能的解决方案。1咋查找应用程序的GC线程数量进行线程转储分析来确定应用程序的GC线程数量:从生产服务器捕获threaddu......
  • update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 60 详细解释这个命
    update-alternatives是一个在Linux系统(尤其是Debian系列,包括Ubuntu)上用于管理多个相同功能的软件版本的命令。它让你可以在系统中安装多个版本的同一个程序(例如多个版本的GCC),并通过优先级和符号链接来控制默认使用哪个版本。让我们详细解释一下以下命令的作用:sudoup......