GC安全点导致停顿时间过长的案例

news2025/3/10 17:26:40

GC安全点导致停顿时间过长的案例

  • 前言
  • 安全点的概念
  • 案例分析
  • 解决方法
  • 如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论!

前言

前段时间在使用G1垃圾收集时,因服务读写压力过大,于是将-XX:MaxGCPauseMillis参数调整为500ms,运行一段时间后发现垃圾收集的停顿时间经常达到3s以上,但实际垃圾收集器进行回收的动作就只占其中的几百毫秒。

MaxGCPauseMillis:最大停顿时间,默认200ms。顾名思义,G1是garbage first。垃圾优先。G1在该最大停顿时间的指定范围内优先收集收益最大(标记垃圾对象最多)的region。

大概的GC日志如下:

[Times:user=1.51 sys=0.67,real=**0.14** secs]
2025-03-07T 21:05:01.376+0800: 3448319Total time for which application threads were stopped :2.2645818 seconds

user:进程执行用户态代码所耗费的处理器时间。
sys:进程执行和心态代码所耗费的处理器时间。
real:执行动作从开始到结束耗费的时钟时间。

前面两个是处理器时间,而最后一个是时钟时间,它们的区别是处理器时间代表的是线程占用处理器一个核心的耗时计数,而时钟时间现实世界中的时间计数,故只需要关注real这个真实感受到的时间即可,因为最终用户只关心发出请求到得到响应所花费的时间,也就是响应速度,而不太关心程序到底是用了多少个线程或者处理器来完成任务。
日志显示本次垃圾收集一共花费了0.14s,但用户线程却足足停顿了2.26秒,两者差距已经远远超出了正常的TTSP(Time To Safepoint)耗时的范畴。

安全点的概念

先理清安全点的概念,避免对于案例有模糊的地方;

安全点:在垃圾收集时,需要STW,也就是要用户线程停止,但用户线程执行时并非在代码指令流的任意位置都能够停顿下来开始垃圾收集,而是强制要求必须执行到达安全点后才能够暂停。

那用户线程如何走到最近的最近安全点呢?
有两种方式:
①抢先式中断:不需要用户线程主动去配合,在垃圾收集发生时,系统会中断所有的用户线程,如果用户线程中断的地方不在安全点上,就恢复这条线程的执行,让它在跑一会再重新中断,直到跑到最近的安全点上。现在几乎没有虚拟机实现采用抢先式中断中暂停线程响应GC事件了。
②主动式中断:当垃圾收集需要中断用户线程时,不直接对线程操作,而是设置一个安全点标志位,各个线程执行过程中会不断轮询这个标志位,一旦发现标志为真时就自己在最近的安全点上主动中断挂起。

案例分析

前言中也说明了用户线程停顿了2.26s,垃圾收集却只花费了0.14s,属实本末倒置了,因为用户线程是主动式中断,于是猜想是否发生垃圾收集时,GC线程在等待用户线程进入安全点这段时间花费了2.26s,最后进入安全点后,GC线程垃圾收集只花费了0.14s?

开始验证:
在启动项目时加入参数-XX:+PrintSafepointStatistics和-XX:PrintSafepointStatisticsCount=1去查看安全点日志,如下:

vmop	[threads: total initially_running wait_to_block]
65968.203: ForceAsyncSafepoint	[931		1		2]
[time: spin block sync cleanup vmop] page_trap_count
[2255  0 2255  11	0]	1

日志显示当前虚拟机(VM Operation),也就是上面的vmop是等待所有用户线程进入到安全点,但是有两个线程特别慢,导致发生长时间的自旋等待。日志中的2255毫秒自旋(spin)时间就是指由于部分线程已走到了安全点,但还有一些特别慢的线程并没有到,所以GC线程无法工作,只能空转等待。
所以怎么找出导致GC线程等待那两个线程呢?
在启动时添加-XX:+SafepointTimeout和-XX:SafepointTimeoutDelay=2000两个参数,让虚拟机在等待线程进入安全点的时间超过2000毫秒时就认为超时,这样就会输出导致问题的线程名称,得到的大概日志如下:

#SafepointSynchroinze::begin: Timeout detected;
#SafepointSynchroinze::begin: Timed out while spinning to reach safepoint.
#SafepointSynchroinze::begin: Threads which did not reach the safepoint:
#"RpcServer.listener,port=24600" #32 daemon prio=5 os_prio=0 tid=0x0000f4c14b22840 nid=0xa621 runnable [0x0000000000000000]
java .lang.Thread.State: RUNNABLE
#SafepointSynchroinze::begin: (End of list)

从日志可以看到是线程名称为“RpcServer.listener,port=24600”导致GC线程发生等待。安全点是以“是否具有让程序长时间执行的特性”为原则进行选定的,所以方法调用、循环跳转、异常跳转这些位置都可能会设置有安全点,但是HotSpot为了避免安全点过多带来过重的负担,对循环还有一项优化措施,认为循环次数较少的话,执行时间应该不会太长,所以是使用int类型或范围更小的数据类型作为索引值的循环默认是不会被防止安全点的,这种循环被称为可数循环。而使用long类型或范围更大的数据类型作为索引值的循环就被称为不可数循环,这种就会被放置安全点。
针对HotSpot有这一优化点,于是翻看RpcServer那块代码发现,很多个上游服务调本服务,有很多连接超时,最后又在清理超时连接的方法发现使用for循环清理,而且是使用int变量记录循环次数,伪代码如下:

for(int i=0;i<list.size;i++){
	...........
	socket.close();
}

这是一个可数循环,HotSpot不会在循环中插入安全点。当垃圾收集发生时,如果RpcServer的Listener线程刚好执行到这个方法里的可数循环时,就必须等待循环全部跑完才能进入安全点,此时其他线程也必须一起等待,所以看起来就是长时间的停顿。

解决方法

上面也说过,可数循环不可放置安全点,那改为不可数循环即可,也就是将int变量改为long类型即可。

如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论!

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

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

相关文章

linux下 jq 截取json文件信息

背景&#xff1a;通过‘登录名‘ 获取该对象的其他个人信息如名字。 环境准备&#xff1a;麒麟操作系统V10 jq安装包 jq安装包获取方式&#xff1a;yum install jq 或 使用附件中的rpm 或 git自行下载 https://github.com/stedolan/jq/releases/download/ 实现过程介绍&am…

软件工程:软件需求之需求分析方法

目录 前言 需求分析方法 工具和方法 具体分析方法 对运行环境的影响 ​编辑 前言 本文重点介绍开展软件需求分析的方法。 需求分析方法 工具和方法 软件需求可以维护在ALM系统中&#xff0c;譬如&#xff1a;doors&#xff0c;codeBeamer等&#xff0c;JIRA适合互联网行…

【网络编程】WSAAsyncSelect 模型

十、基于I/O模型的网络开发 接着上次的博客继续分享&#xff1a;select模型 10.8 异步选择模型WSAAsyncSelect 10.8.1 基本概念 WSAAsyncSelect模型是Windows socket的一个异步I/O 模型&#xff0c;利用这个模型&#xff0c;应用程序 可在一个套接字上接收以Windows 消息为基…

视觉-语言模型-出发点CLIP--(精读论文)

阅读建议&#xff1a;配合这个源码分析阅读效果更加 研究背景和目的 介绍当前计算机视觉系统依赖固定类别标签训练的局限性&#xff0c;以及自然语言监督作为一种有潜力替代方式的研究现状。强调论文旨在探索从自然语言监督中学习可迁移视觉模型&#xff0c;实现零样本学习&a…

任务11:路由器配置与静态路由配置

目录 一、概念 二、路由器配置 三、配置静态路由CSDN 原创主页&#xff1a;不羁https://blog.csdn.net/2303_76492156?typeblog 一、概念 1、路由器的作用&#xff1a;通过路由表进行数据的转发。 2、交换机的作用&#xff1a;通过学习和识别 MAC 地址&#xff0c;依据 M…

Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF

基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle

LeeCode题库第四十六题

46.全排列 项目场景&#xff1a; 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&am…

LangChain4j开发RAG入门示例

本文将详细介绍如何基于Java语言&#xff0c;使用Langchain4j开源框架、Milvus向量数据、阿里Qwen大模型&#xff0c;开发一个RAG入门级简单示例。本示例虽然简单&#xff0c;但涉及到多个知识点&#xff0c;包括&#xff1a;Milvus初始化、Embedding模型、文档切片、Springboo…

快速从C过度C++(一):namespace,C++的输入和输出,缺省参数,函数重载

&#x1f4dd;前言&#xff1a; 本文章适合有一定C语言编程基础的读者浏览&#xff0c;主要介绍从C语言到C过度&#xff0c;我们首先要掌握的一些基础知识&#xff0c;以便于我们快速进入C的学习&#xff0c;为后面的学习打下基础。 这篇文章的主要内容有&#xff1a; 1&#x…

课程《Deep Learning Specialization》

在coursera上&#xff0c;Deep Learning Specialization 课程内容如下图所示&#xff1a;

微服务与消息队列RabbitMQ

简介 同步模式 异步模式 内容 解决方案RabbitMQ 同步调用的优缺点 同步调用的优势是什么&#xff1f; 时效性强&#xff0c;等待到结果后才返回。 同步调用的问题是什么&#xff1f; 拓展性差性能下降级联失败问题

苹果 M3 Ultra 芯片深度解析:AI 时代的性能革命

2025 年 3 月 5 日&#xff0c;苹果正式发布了其史上最强 PC 芯片 ——M3 Ultra。这款基于 UltraFusion 封装技术的旗舰级 SoC&#xff0c;不仅延续了苹果芯片在能效比上的传统优势&#xff0c;更通过架构创新与硬件升级&#xff0c;将 AI 计算能力推向了新高度。本文将从性能突…

通义千问:Qwen2.5-0.5B模型架构解释

通义千问:Qwen2.5-0.5B模型架构解释 1. 模型权重文件 .mdl、.msc:存储模型核心参数,是模型训练后学习到的知识载体,包含神经网络各层权重,加载后模型才能执行推理、生成等任务。 .mdl文件:通常是模型的核心权重数据文件,存储神经网络各层的权重参数、张量等关键数据,是…

【Linux】冯诺依曼体系与操作系统理解

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充&#xff1a;理解系统调用…

玩转ChatGPT:GPT 深入研究功能

一、写在前面 民间总结&#xff1a; 理科看Claude 3.7 Sonnet 文科看DeepSeek-R1 那么&#xff0c;ChatGPT呢&#xff1f; 看Deep Research&#xff08;深入研究&#xff09;功能。 对于科研狗来说&#xff0c;在这个文章爆炸的时代&#xff0c;如何利用AI准确、高效地收…

虚函数和虚表的原理是什么?

虚函数是一个使用virtual关键字声明的成员函数&#xff0c;在基类中声明虚函数&#xff0c;在子类中可以使用override重写该函数。虚函数根据指针或引用指向的实际对象调用&#xff0c;实现运行时的多态。 虚函数表&#xff08;虚表&#xff09;是一个用于存储虚函数地址的数组…

laravel es 相关代码 ElasticSearch

来源&#xff1a; github <?phpnamespace App\Http\Controllers;use Elastic\Elasticsearch\ClientBuilder; use Illuminate\Support\Facades\DB;class ElasticSearch extends Controller {public $client null;public function __construct(){$this->client ClientB…

字节跳动C++客户端开发实习生内推-抖音基础技术

智能手机爱好者和使用者&#xff0c;追求良好的用户体验&#xff1b; 具有良好的编程习惯&#xff0c;代码结构清晰&#xff0c;命名规范&#xff1b; 熟练掌握数据结构与算法、计算机网络、操作系统、编译原理等课程&#xff1b; 熟练掌握C/C/OC/Swift一种或多种语言&#xff…

C语言_数据结构总结6:链式栈

纯c语言代码&#xff0c;不涉及C 顺序栈的实现&#xff0c;欢迎查看这篇文章&#xff1a;C语言_数据结构总结5&#xff1a;顺序栈-CSDN博客 0. 结构单元 #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct Linknode { ElemType…

基于DeepSeek的智慧医药系统(源码+部署教程)

运行环境 智慧医药系统运行环境如下&#xff1a; 前端&#xff1a; HTMLCSS后端&#xff1a;Java AIGCDeepseekIDE工具&#xff1a;IDEA技术栈&#xff1a;Springboot HTMLCSS MySQL 主要角色 智慧医药系统主要分为两个角色。 游客 尚未进行注册和登录。具备登录注册、…