掌握 JVM 垃圾收集线程:简化 VM 选项

垃圾收集阶段对于任何 Java 应用程序都至关重要。主要目标是保持高吞吐量和低延迟之间的平衡。通过配置垃圾收集器,我们可以提高性能,或者至少推动应用程序朝着特定的方向发展。

垃圾收集周期越短越好。因此,分配给垃圾收集器的资源越多,它的工作速度就越快,从而整体上改善我们的应用程序。为垃圾收集器分配更多资源是一个合理的想法,但它并不像听起来那么简单。

在本文中,我们将了解线程数对应用程序性能的影响。本文主要介绍直接在主机上运行的应用程序。**但是,我们也可以将这些见解应用于容器化应用程序。 **

垃圾收集线程

通常,垃圾收集器会使用多个线程来促进正确及时的收集过程。然而,我们通常对与之连接的两种类型的线程感兴趣:并行线程和并发线程。

请注意,某些算法可能会出于不同目的使用更多线程。 例如,G1 垃圾收集器会使用更多线程执行某些内部任务。

1.并发线程

这些线程的名称是不言而喻的。 垃圾收集器在并发阶段使用并发线程。 例如,CMS 将使用它们来清理旧代。提供更多线程有助于减少应用程序的延迟。

同时,完全 STW(stop-the-world)垃圾收集器不会使用它们,因为它们没有并发阶段。

2. 并行线程

这些线程在 STW 阶段发挥作用。 尽管名称如此,但它们并不与应用程序并行运行。这些线程将彼此并行运行,以减少垃圾收集暂停。

因此,更多的并行线程会减少 STW 时间。但是,我们需要验证所有假设并运行适当的基准测试。JVM使用合理的启发式方法根据 CPU 核心数来确定默认的垃圾收集线程数。这个想法很简单:更多核心等于更多线程:

在具有 N 个硬件线程且 N 大于 8 的机器上,并行收集器使用 N 的固定分数作为垃圾收集器线程数。对于较大的 N 值,该分数约为 5/8。当 N 值低于 8 时,使用的数字为 N。在选定的平台上,该分数下降到 5/16。

因此,在八核机器上,我们将有八个收集器线程;在三十二核的机器上,这个数字将是二十个。

手动配置

虽然 JVM 提供了有关默认线程数的合理启发式方法,但有时我们想要覆盖它们。 我们可以使用 VM 选项手动配置线程数。 显式配置可以更好地控制应用程序,并允许我们使用更合适的值覆盖默认值。

我们可以使用几个标志来配置线程数。正如我们所讨论的,垃圾收集过程通常使用两种类型的线程:并发和并行;我们有单独的参数来控制它们:

-XX:ParallelGCThreads=<number>
-XX:ConcGCThreads=<threads>

手动配置的主要问题是我们应该深刻理解我们的应用程序: 不完全是领域逻辑和类之间的联系,而是影响堆的资源消耗和进程。

我们还必须了解 JVM 和应用程序使用的垃圾收集算法。理解不当可能会导致性能下降。**同时,向 SerialGC 添加更多并发线程不会对其产生任何影响。 **

线程数

让我们使用一个简单的应用程序来检查垃圾收集线程。但是,我们不会在空闲应用程序上看到所有线程。因此,我们需要对垃圾收集器施加压力,以便它尝试利用所有资源:

public class GcThreadsOnOutOfMemoryErrorBenchmark {public static void main(String[] args) {LinkedList<String> strings = new LinkedList<>();while (true) {strings.add(new String("Hello World!!!!"));}}
}

此代码将导致OutOfMemoryError并使应用程序崩溃。但是,这正是我们强制它使用所有可用的垃圾收集线程所需要的。要在**OutOfMemoryError时创建线程转储,我们可以使用以下命令:

-XX:OnOutOfMemoryError= "kill -3 %p"

我们把并发线程数改为2个,并行线程数改为8个,可以使用*-XX:+PrintCommandLineFlags*来验证一下参数:

-XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=268435456 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=268435456 -XX:MinHeapSize=6815736 -XX:OnOutOfMemoryError=kill -3 %p -XX:ParallelGCThreads=8 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC

根据之前的 VM 标志列表,我们将使用 G1GC 来查看并发和并行线程。 此外,我们还可以看到特定于此算法的其他垃圾收集线程:

Threads class SMR info:
_java_thread_list=0x0000600002d0ae80, length=12, elements={
0x0000000142016c00, 0x000000014380dc00, 0x000000014380b800, 0x00000001420d1600,
0x00000001420cf600, 0x000000014180b000, 0x00000001420d3400, 0x00000001420d6800,
0x000000014180d800, 0x0000000143009800, 0x0000000141812a00, 0x0000000141813000
}"main" #1 [8451] prio=5 os_prio=31 cpu=68.74ms elapsed=1.41s tid=0x0000000142016c00 nid=8451 runnable  [0x000000016d7d6000]java.lang.Thread.State: RUNNABLE"Reference Handler" #8 [31747] daemon prio=10 os_prio=31 cpu=0.43ms elapsed=1.40s tid=0x000000014380dc00 nid=31747 runnable  [0x000000016e742000]java.lang.Thread.State: RUNNABLE"Finalizer" #9 [22531] daemon prio=8 os_prio=31 cpu=0.14ms elapsed=1.40s tid=0x000000014380b800 nid=22531 in Object.wait()  [0x000000016e94e000]java.lang.Thread.State: WAITING (on object monitor)"Signal Dispatcher" #10 [31235] daemon prio=9 os_prio=31 cpu=0.07ms elapsed=1.40s tid=0x00000001420d1600 nid=31235 waiting on condition  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Service Thread" #11 [23043] daemon prio=9 os_prio=31 cpu=0.15ms elapsed=1.40s tid=0x00000001420cf600 nid=23043 runnable  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Monitor Deflation Thread" #12 [30723] daemon prio=9 os_prio=31 cpu=0.03ms elapsed=1.40s tid=0x000000014180b000 nid=30723 runnable  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread0" #13 [23555] daemon prio=9 os_prio=31 cpu=18.32ms elapsed=1.40s tid=0x00000001420d3400 nid=23555 waiting on condition  [0x0000000000000000]java.lang.Thread.State: RUNNABLENo compile task"C1 CompilerThread0" #16 [24067] daemon prio=9 os_prio=31 cpu=18.20ms elapsed=1.40s tid=0x00000001420d6800 nid=24067 waiting on condition  [0x0000000000000000]java.lang.Thread.State: RUNNABLENo compile task"Sweeper thread" #17 [30211] daemon prio=9 os_prio=31 cpu=0.04ms elapsed=1.40s tid=0x000000014180d800 nid=30211 runnable  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Common-Cleaner" #18 [29699] daemon prio=8 os_prio=31 cpu=0.20ms elapsed=1.40s tid=0x0000000143009800 nid=29699 waiting on condition  [0x000000016f7a2000]java.lang.Thread.State: TIMED_WAITING (parking)"Monitor Ctrl-Break" #19 [24835] daemon prio=5 os_prio=31 cpu=14.32ms elapsed=1.37s tid=0x0000000141812a00 nid=24835 runnable  [0x000000016f9ae000]java.lang.Thread.State: RUNNABLE"Notification Thread" #20 [25347] daemon prio=9 os_prio=31 cpu=0.04ms elapsed=1.37s tid=0x0000000141813000 nid=25347 runnable  [0x0000000000000000]java.lang.Thread.State: RUNNABLE"VM Thread" os_prio=31 cpu=16.53ms elapsed=1.41s tid=0x000000014170e060 nid=19971 runnable  "GC Thread#0" os_prio=31 cpu=619.54ms elapsed=1.41s tid=0x0000000141706da0 nid=12547 runnable  "GC Thread#1" os_prio=31 cpu=672.72ms elapsed=1.36s tid=0x000000014161b6d0 nid=28931 runnable  "GC Thread#2" os_prio=31 cpu=559.43ms elapsed=1.36s tid=0x000000014161bb70 nid=25859 runnable  "GC Thread#3" os_prio=31 cpu=914.80ms elapsed=1.36s tid=0x000000014161c010 nid=26115 runnable  "GC Thread#4" os_prio=31 cpu=613.24ms elapsed=1.36s tid=0x000000014161c4b0 nid=28163 runnable  "GC Thread#5" os_prio=31 cpu=491.98ms elapsed=1.36s tid=0x000000014161c950 nid=27907 runnable  "GC Thread#6" os_prio=31 cpu=844.52ms elapsed=1.36s tid=0x000000014161cdf0 nid=27395 runnable  "GC Thread#7" os_prio=31 cpu=662.01ms elapsed=1.36s tid=0x000000014161d290 nid=27139 runnable  "G1 Main Marker" os_prio=31 cpu=0.13ms elapsed=1.41s tid=0x0000000141707470 nid=14339 runnable  "G1 Conc#0" os_prio=31 cpu=17.27ms elapsed=1.41s tid=0x0000000141707d10 nid=13827 runnable  "G1 Conc#1" os_prio=31 cpu=17.35ms elapsed=1.09s tid=0x000000014161dc30 nid=43267 runnable  "G1 Refine#0" os_prio=31 cpu=1.00ms elapsed=1.41s tid=0x0000000141709ba0 nid=16643 runnable  "G1 Service" os_prio=31 cpu=0.41ms elapsed=1.41s tid=0x000000014170a4d0 nid=21507 runnable  "VM Periodic Task Thread" os_prio=31 cpu=0.22ms elapsed=1.37s tid=0x000000014161a930 nid=25603 waiting on condition

虽然手动配置可能很有用,但也可能导致严重问题。 我们可以将自动计算与限制相结合来避免错误。 以下标志可以帮助我们自动计算线程数,但也允许我们设置一些限制:

-XX:+AdaptiveGCThreading
-XX:ParallelGCMaxThreads

线程转储分析

我们可以在应用程序中创建线程转储,因为它们不会产生太多开销。**最好多次创建线程转储,每次之间都留出短暂的停顿,例如 10 秒。 **

虽然线程转储通常可读,但更方便的是可视化和比较随时间变化的信息。 标准工具可以帮助我们可视化、过滤和搜索,但它们没有提供比较转储的便捷方法

yCrash 提供了一些工具,可以帮助分析和测试应用程序的性能。其中 之一是fastThread 它可以根据线程转储创建综合报告:

fastThread 报告摘要
如图:快速线程报告 摘要

然后可以对这些报告进行比较和审查:

在这里插入图片描述

如图:快速线程比较总结

可以通过 yCrash 仪表板访问这些报告,以访问同一应用程序中的所有报告。

另外,我们可以在同一个报告页面上检查线程池:

fastThread 线程池
如图:快速线程线程池

结论

垃圾收集线程的默认配置通常都很好。 但是,JVM 允许手动配置,我们可以使用它来微调应用程序并提高其性能。此过程应包括监控和分析。

线程转储不会产生太多开销 ,因此我们可以定期运行它们。 这样,我们可以在不同阶段监控应用程序的变化,这有助于识别热点。

然而,为了更好地了解应用程序的问题,必须进行几次线程转储,并在每次转储之间进行短暂的暂停。

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

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

相关文章

RS485串口通信:【图文详讲】

RS485&#xff0c;RS的意义为Recommended Standard的缩写&#xff0c;也就是推荐标准&#xff0c;是一种常用的半双工-异步-串行通信总线。半双工的意思就是两者通信时&#xff0c;同一时刻&#xff0c;只能由其中一方发送&#xff0c;另一方只能接收&#xff0c;不可以同时收发…

Java 每日一刊(第18期):集合

文章目录 前言1. Java 集合框架概述1.1 Java 集合框架的定义和意义1.2 Java 集合框架的历史演进1.3 集合框架的基本组成部分1.4 Java 集合的优势1.5 Java 集合与数组的区别与关系 2. Java 集合框架的核心接口2.1 Collection 接口2.2 List 接口2.3 Set 接口2.4 Queue 接口2.5 Ma…

共享单车轨迹数据分析:以厦门市共享单车数据为例(九)

副标题&#xff1a;基于站点800m范围内评价指标探究——以吕厝站为例 上篇文章我们以厦门市为例&#xff0c;来通过POI和优劣解距离法&#xff08;TOPSIS&#xff09;来研究厦门岛内以800m作为辐射范围的地铁站哪些地铁站发展的最好&#xff0c;根据综合得分指数可以知道&…

【Linux】【操作】Linux操作集锦系列之七——Linux环境下如何查看CPU使用情况(利用率等)

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;Linux技术&…

AutoGen实现多代理-Planning_and_Stock_Report_Generation(六)

1. 案例背景 本节内容是构建Agent组&#xff0c;通过广播模式&#xff0c;实现管理者对agent工作流的管理。本实验链接&#xff1a;传送门 2. 代码实践 2.1 环境设置 llm_config{"model": "gpt-4-turbo"}# 工作任务描述 task "Write a blogpost a…

Cyberduck网络鸭-访问远程文件客户端新选择

Cyberduck 是一款适用于 macOS 和 Windows 的自由文件传输客户端。适用于 Linux、macOS 和 Windows 的命令行界面 (CLI)。核心库用于Mountain Duck。 官网&#xff1a;https://cyberduck.io/download/ 开源地址&#xff1a; https://cyberduck.io/download/ 支持协议很多&…

国庆同欢,祖国昌盛!肌肉纤维启发,水凝胶如何重构聚合物

在这个国庆佳节&#xff0c;我们共同感受祖国的繁荣昌盛&#xff0c;同时也迎来了知识的探索之旅。今天来了解聚合物架构的重构的研究——《Hydrogel‐Reactive‐Microenvironment Powering Reconfiguration of Polymer Architectures》发表于《Advanced Science》。材料科学不…

消费电子制造企业如何使用SAP系统提升运营效率与竞争力

在当今这个日新月异的消费电子市场中&#xff0c;企业面临着快速变化的需求、激烈的竞争以及不断攀升的成本压力。为了在这场竞赛中脱颖而出&#xff0c;消费电子制造企业纷纷寻求数字化转型的突破点&#xff0c;其中&#xff0c;SAP系统作为业界领先的企业资源规划(ERP)解决方…

怀孕之天赋共享:其实人身体没变,完全是天赋共享

关于怀孕天赋共享&#xff0c;有人说&#xff0c;是不是怀孕导致身体变化&#xff1f; 并没有。下面这个就是案例。你总不能说&#xff0c;小孩生下来身体立即改变吧&#xff1f;

World of Warcraft [CLASSIC] Engineering 421-440

工程学421-440 World of Warcraft [CLASSIC] Engineering 335-420_魔兽世界宗师级工程学需要多少点-CSDN博客 【萨隆邪铁锭】421-425 学习新技能&#xff0c;其他都不划算&#xff0c;只能做太阳瞄准镜 【太阳瞄准镜】426、427、428、429 【随身邮箱】430 这个基本要做的&am…

基于SSM的农产品仓库管理系统【附源码】

基于SSM的农产品仓库管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统概要设计 4.2 系统功能结构设计 4.3 数据库设计 4.3.1 数据库E-R图设计 4.3.2 数据库表结构设计 5 系统实现 5.1 管理员功能介绍 5.1.1 用户管…

ios内购支付-支付宝APP支付提现

文章目录 前言一、IOS内购支付&#xff08;ios订单生成自己写逻辑即可&#xff09;1.支付回调票据校验controller1.支付回调票据校验server 二、安卓APP支付宝支付1.生成订单返回支付宝字符串&#xff08;用于app拉起支付宝&#xff0c;这里用的是证书模式&#xff09;2.生成订…

Java 死锁及避免讲解和案例示范

在大型分布式系统中&#xff0c;死锁是一种常见但难以排查的并发问题。特别是在 Java 领域&#xff0c;死锁问题可能导致系统崩溃或卡顿。本文将以电商交易系统为例&#xff0c;详细讲解如何识别和避免 Java 程序中的死锁问题&#xff0c;确保系统高效运行。 1. 什么是死锁&am…

Cesium 路径导航线

Cesium 路径导航线 const points [-115.05079620730267, 37.19786588187864,-115.22324534761827, 37.543541965531986,-115.47419222019222, 37.615105164973855,-115.48787694581283, 37.40861889557443,-115.41627083519458, 37.11794056537019,-115.1758997349438, 36.951…

C0007.Clion中添加ui文件及运行的完整步骤

1.创建ui文件 选择Ui文件目录,右击,打开Qt Designer; 创建完成后,保存ui界面,并且命名为test.ui; 2.新建头文件test.h 在include目录中,新建头文件,文件名为test.h 3.新建test.cpp源文件

Web安全 - 重放攻击(Replay Attack)

文章目录 OWASP 2023 TOP 10导图1. 概述2. 重放攻击的原理攻击步骤 3. 常见的重放攻击场景4. 防御重放攻击的技术措施4.1 使用时效性验证&#xff08;Time-Based Tokens&#xff09;4.2 单次令牌机制&#xff08;Nonce&#xff09;4.3 TLS/SSL 协议4.4 HMAC&#xff08;哈希消息…

YOLOv11尝鲜测试五分钟极简配置

ultralytics团队在最近又推出了YOLOv11&#xff0c;不知道在有生之年能不能看到YOLOv100呢哈哈。 根据官方文档&#xff0c;在 Python>3.8并且PyTorch>1.8的环境下即可安装YOLOv11&#xff0c;因此之前YOLOv8的环境是可以直接用的。 安装YOLOv11&#xff1a; pip instal…

DevExpress WinForms v24.1新版亮点:富文本编辑器、电子表格组件功能升级

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

VMware 虚拟机 下载安装 Centos7 和Windows10 镜像源

准备工作 下载 VMware链接&#xff1a;稍后发布链接 Centos7完整版链接&#xff1a;https://www.123865.com/ps/EF7OTd-mdAnH Centos7mini版链接&#xff1a;https://www.123865.com/ps/EF7OTd-1dAnH Windows10链接&#xff1a;https://www.123865.com/ps/EF7OTd-4dAnH 演示环境…

Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)

文章目录 1&#xff0c;shell核心概念1. 1&#xff0c;变量1. 2. 引号1. 3. 循环1. 4. 条件判断1. 5. 函数1. 6. 重定向1. 7. 管道1. 8. 通配符 2&#xff0c;案例 本文通过介绍Linux Shell编程中最重要的十个核心概念&#xff0c;帮助初学者快速入门。 1&#xff0c;shell核心…