首页 > 编程语言 >Java 性能调优:调整 GC 线程以获得最佳结果

Java 性能调优:调整 GC 线程以获得最佳结果

时间:2024-09-25 11:56:40浏览次数:3  
标签:Java 回收 调优 GC 应用程序 JVM 线程 CPU


    垃圾回收 (GC) 在 Java 的内存管理中起着重要作用。它有助于回收不再使用的内存。垃圾回收器使用自己的线程集来回收内存。这些线程称为 GC 线程。有时,JVM 最终可能会有太多或太少的 GC 线程。在这篇文章中,我们将讨论为什么 JVM 最终会拥有太多/太少的 GC 线程,它的后果,以及解决这些问题的潜在解决方案。

如何查找应用程序的 GC 线程计数

    您可以通过执行线程转储分析来确定应用程序的 GC 线程计数,如下所述:

  1. 从生产服务器捕获线程转储。
  2. 使用线程转储分析工具分析转储。
  3. 该工具将立即报告 GC 线程计数,如下图所示。

Java 性能调优:调整 GC 线程以获得最佳结果_开发语言

图 1:fastThread 工具报告 GC 线程计数

如何设置 GC 线程数

    您可以通过设置以下两个 JVM 参数来手动调整 GC 线程数:

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

默认的 GC 线程计数是多少?

    如果您没有使用上述两个 JVM 参数显式设置 GC 线程计数,则默认 GC 线程计数将根据服务器/容器中的 CPU 数量得出。

  • –XX:ParallelGCThreads Default:在 Linux/x86 机器上,它是根据以下公式派生的:
if (num of processors <=8) {      return num of processors; } else {    return 8+(num of processors-8)*(5/8); }

    因此,如果您的 JVM 在具有 32 个处理器的服务器上运行,那么该值将为:23(即 8 + (32 – 8)*(5/8))。ParallelGCThread

  • -XX:ConcGCThreads Default:它是根据公式派生的:
max((ParallelGCThreads+2)/4, 1)

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

  • ParallelGCThread值将为:23(即 8 + (32 – 8)*(5/8))。
  • ConcGCThreads值将为:6 (i.e. max(25/4, 1)。

JVM 最终会有太多的 GC 线程吗?

    您的 JVM 可能会无意中拥有太多的 GC 线程,而您通常不会意识到。这通常是因为默认的 GC 线程数是根据服务器或容器中的 CPU 数量自动确定的。

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

    如果您在这台 128 CPU 的计算机上运行多个 JVM,则每个 JVM 最终可能会有大约 100 个 GC 线程。这可能会导致资源使用过多,因为所有这些线程都在争夺相同的 CPU 资源。这个问题在容器化环境中尤为明显,因为多个应用程序共享相同的 CPU 内核。这将导致 JVM 分配的 GC 线程数超过必要数量,这可能会降低整体性能。

为什么 GC 线程过多是一个问题?

    虽然 GC 线程对于高效的内存管理至关重要,但拥有过多的 GC 线程可能会导致 Java 应用程序面临重大的性能挑战。

  1. 增强的上下文切换: 当 GC 线程数过多时,操作系统必须在这些线程之间频繁切换。这会导致上下文切换开销增加,其中更多的 CPU 周期用于管理线程,而不是执行应用程序的代码。因此,您的应用程序可能会显着减慢速度。
  2. CPU 开销: 每个 GC 线程都会消耗 CPU 资源。如果同时处于活动状态的线程太多,它们可能会争夺 CPU 时间,从而减少可用于应用程序主要任务的处理能力。这种竞争会降低应用程序的性能,尤其是在 CPU 资源有限的环境中。
  3. 内存争用: 如果 GC 线程数量过多,则内存资源争用可能会增加。多个线程尝试同时访问和修改内存可能会导致锁争用,这会进一步降低应用程序的速度,并可能导致性能瓶颈。
  4. GC 暂停时间增加,通量降低: 当过多的 GC 线程处于活动状态时,垃圾回收过程的效率可能会降低,从而导致应用程序暂时停止的 GC 暂停时间更长。这些长时间的暂停可能会导致应用程序出现明显的延迟或卡顿。此外,随着花在垃圾回收而不是处理请求上的时间越来越多,应用程序的整体吞吐量可能会降低,每秒处理的事务或请求更少,并影响其在负载下扩展和执行的能力。
  5. 更高的延迟: 由于线程数过多而导致 GC 活动增加,这可能会导致响应用户请求或处理任务的延迟增加。这对于需要低延迟的应用程序(例如实时系统或高频交易平台)来说尤其成问题,在这些应用程序中,即使是轻微的延迟也可能产生重大后果。
  6. 递减: 超过某个点后,添加更多 GC 线程不会提高性能。相反,它会导致收益递减,其中管理这些线程的开销超过了更快垃圾回收的好处。这可能会导致应用程序性能下降,而不是预期的优化。

为什么 GC 线程太少是一个问题?

    虽然 GC 线程过多会产生性能问题,但 GC 线程太少对 Java 应用程序来说同样会出现问题。原因如下:

  1. 更长的垃圾回收时间: 如果 GC 线程较少,垃圾回收过程可能需要更长的时间才能完成。由于可用于处理工作负载的线程较少,因此回收内存所需的时间会增加,从而导致 GC 暂停时间延长。
  2. 应用程序延迟增加: 较长的垃圾回收时间会导致延迟增加,尤其是对于需要低延迟操作的应用程序。用户可能会遇到延迟,因为应用程序在等待垃圾回收完成时变得无响应。
  3. 降低吞吐量: 较少的 GC 线程数意味着垃圾回收器无法高效工作,从而导致整体吞吐量降低。您的应用程序每秒处理的请求或事务可能会减少,从而影响其在负载下扩展的能力。
  4. CPU 利用率低下: 如果 GC 线程太少,CPU 核心在垃圾回收期间可能无法得到充分利用。这可能会导致可用资源的使用效率低下,因为某些内核保持空闲状态,而其他内核则负担过重。
  5. OutOfMemoryErrors 和内存泄漏的风险增加:如果垃圾回收器由于线程太少而无法跟上内存分配的速率,则它可能无法足够快地回收内存。这会增加应用程序内存不足的风险,从而导致潜在的崩溃。此外,GC 线程不足会减慢垃圾回收过程,从而允许更多未使用的对象在内存中积累,从而加剧内存泄漏。随着时间的推移,这可能会导致内存使用过多并进一步降低应用程序性能。OutOfMemoryErrors

优化 GC 线程数的解决方案

    如果您的应用程序由于 GC 线程数量过多或不足而出现性能问题,请考虑使用上述 JVM 参数手动设置 GC 线程计数:

  • -XX:ParallelGCThreads=n 
  • -XX:ConcGCThreads=n

    在生产环境中进行这些更改之前,必须研究应用程序的 GC 行为。首先使用工具收集和分析 GC 日志。此分析将帮助您确定当前线程计数是否导致性能瓶颈。根据这些见解,您可以对 GC 线程数进行明智的调整,而不会引入新问题

  • 注意:始终先在受控环境中测试更改,以确认它们提高了性能,然后再将其部署到生产环境中。

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

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

相关文章

  • 什么是带有示例的 Java 中的交错数组?
    Java中的交错数组交错数组,也称为数组数组,是一种数据结构,其中数组用于存储其他数组。交错数组的主要特征是主数组的每个元素可以具有不同的大小,从而允许在二维结构中使用可变的列长度。为了理解Jagged数组的概念,让我们考虑一个例子。假设我们想要存储有关学生及其各自成绩的信息......
  • 使用 AuraDB 免费版构建 Java 微服务
        对于今天的冒险,我们希望构建一个Java微服务,它连接到Neo4jAuraDBFree数据库中的图形数据并与之交互。我们的数据是 Goodreads数据集的精简版本,其中包括书籍、作者和评论信息。虽然书籍和作者非常适合MongoDB等文档数据库,但一旦您将评论添加到组合中,关系的细微差别......
  • 了解 Java 中的浮点精度问题
    Java浮点数看起来很熟悉在 Java 中,我们有两种类型的浮点数:和.所有 Java开发人员都知道它们,但无法回答以下模因中描述的简单问题:floatdouble你够机器人吗?您对Float和Double了解多少?float并表示浮点数。使用32位,而使用64位,可用于十进制或小数部分。但这实际上意味着什......
  • 基于Java的宠物之家小程序 宠物服务小程序【源码+调试】
    精彩专栏推荐订阅:在下方主页......
  • 【JUC并发编程系列】深入理解Java并发机制:阻塞队列详解与简单纯手写(七、BlockingQueu
    文章目录【JUC并发编程系列】深入理解Java并发机制:阻塞队列详解与简单纯手写(七、BlockingQueue、ArrayBlockingQueue、LinkedBlocking)1.简单回顾1.1数组结构和链表结构1.1.1数组结构1.1.2链表结构1.2有界队列与无界队列1.3Lock锁使用回顾2.什么是阻塞队列3.B......
  • 【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、
    文章目录【JUC并发编程系列】深入理解Java并发机制:Volatile从底层原理解析到高级应用技巧(六、Volatile关键字、JMM、重排序、双重检验锁)1.Volatile的特性2.Volatile的用法3.CPU多核硬件架构剖析4.JMM内存模型4.1主要特性4.2JMM的工作原理4.3实现机制5.JMM八......
  • 【JUC并发编程系列】深入理解Java并发机制:线程局部变量的奥秘与最佳实践(五、ThreadLo
    文章目录【JUC并发编程系列】深入理解Java并发机制:线程局部变量的奥秘与最佳实践(五、ThreadLocal原理、对象之间的引用)1.基本API介绍2.简单用法3.应用场景4.Threadlocal与Synchronized区别5.内存溢出和内存泄漏5.2内存溢出(MemoryOverflow)5.2内存泄漏(Mem......
  • java中关于多态的案例
    判断下列代码的输出结果:classA{publicvoidshow(){show2();}publicvoidshow2(){System.out.println("我");}}classBextendsA{/*publicvoidshow(){show2();}*/publicv......
  • AGC067B 做题记录
    link考虑时光倒流,相当于每次选择一个区间,若未覆盖的位置的颜色都相同,则把区间里的所有位置覆盖,一个序列合法当且仅当经过若干次覆盖后\([1,n]\)中所有位置都被覆盖。容斥,考虑经过若干次覆盖后,还剩未覆盖位置集合\(S\),满足不存在可以继续覆盖\(S\)中的位置的区间。\(S\)把......
  • 基于Java+SpringBoot+Mysql明星资讯信息系统功能设计与实现七
    一、前言介绍:1.1项目摘要随着社会的不断进步和人们生活水平的提高,娱乐产业在全球范围内得到了迅猛发展。明星作为娱乐产业的重要组成部分,其资讯的获取和传播成为了广大观众和粉丝关注的焦点。因此,研究明星资讯的课题背景,可以深入了解娱乐产业的发展趋势和市场需求。互联......