jvmti_JVMTI标记如何影响GC暂停

jvmti

这篇文章分析了为什么Plumbr Agents在某些情况下以及如何延长GC暂停的时间。 对基本问题进行故障诊断揭示了有关在GC暂停期间如何处理JVMTI标记的有趣见解。

发现问题

我们的一位客户抱怨说,附加了Plumbr代理后,应用程序的响应速度明显降低。 通过分析GC日志,我们发现GC时间异常。 这是不带Plumbr的JVM摘录的GC日志:

2015-01-30T17:19:08.965-0200: 182.816: [Full GC (Ergonomics) 
[PSYoungGen: 524800K->0K(611840K)] 
[ParOldGen: 1102620K->1103028K(1398272K)] 1627420K->1103028K(2010112K), 
[Metaspace: 2797K->2797K(1056768K)], 0.9563188 secs] 
[Times: user=7.32 sys=0.01, real=0.96 secs]

这是附加了Plumbr Agent的:

2015-02-02T17:40:35.872-0200: 333.166: [Full GC (Ergonomics) 
[PSYoungGen: 524800K->0K(611840K)] 
[ParOldGen: 1194734K->1197253K(1398272K)] 1719534K->1197253K(2010112K), 
[Metaspace: 17710K->17710K(1064960K)], 1.9900624 secs] 
[Times: user=7.94 sys=0.01, real=1.99 secs]

异常隐藏在经过的时间中。 实时时间是经过的实际时间。 如果您手里拿着秒表,那么实时将等于该数字。 用户时间 (加上系统时间)是测量过程中消耗的总CPU时间。 如果多个内核上有多个线程,则该时间可能大于实时时间。 因此,对于并行GC,实时时间应大致等于(用户时间/线程数)。 在我的机器上,该比率应该接近7,而没有Plumbr Agent的情况下确实是如此。 但是使用Plumbr时,该比率大大下降。 绝对不行!

初步调查

有了这样的证据,以下是最可能的假设:

  1. Plumbr使JVM在每个GC之后执行一些繁重的单线程操作
  2. Plumbr导致JVM使用更少的线程进行垃圾回收

但是,仅查看GC日志中的一行,就无法进行更狭窄的观察,因此我们继续进行可视化上述比率:

gc-pause-long

图表上的下降恰好发生在Plumbr发现内存泄漏的那一刻。 根本原因分析过程中,GC可能会给GC带来一些额外负担,但永久影响GC暂停时间绝对不是我们为代理特意设计的功能。 这种行为有利于第一个假设,因为我们不太可能在运行时影响GC线程的数量。

创建一个隔离的测试用例花费了一段时间,但是在以下约束的帮助下,我们可以钉上它:

  1. 应用程序必须泄漏内存以供Plumbr检测
  2. 应用程序必须经常暂停以进行垃圾收集
  3. …以及作为突破时刻–应用程序必须具有较大的活动集,这意味着在Full GC中幸存的对象数量必须很大。

编译了足够小的测试用例后,可以放大根本原因检测范围。 合理的方法是打开和关闭Plumbr代理的各个功能,然后查看问题将在哪种配置下重现。

通过这种简单的搜索,我们设法将问题定位到Plumbr Agent执行的单个操作。 JVMTI标记关闭后,问题消失了。 在分析gc根和引用链的路径时 ,我们标记堆上的每个对象。 显然,GC时间在某种程度上受我们生成的标签的影响。

寻找根本原因

但是,尚不清楚为什么GC暂停会延长。 垃圾会被Swift收集,并且大多数带标签的对象应该符合GC的条件。 但是发现的是,存在大量活动集(这是内存泄漏的症状之一),其中保留了许多带标签的对象。

但是,即使对活动集中的所有对象都进行了标记,这也不应线性影响GC时间。 GC完成后,我们会收到有关所有已收集的标记对象的通知,但活动集不在这些对象之内。 这使人们想知道,HotSpot是否出于某种奇怪的原因在每个GC之后迭代所有标记的对象。

为了验证要求,可以查看热点源代码。 经过一番挖掘之后,我们最终到达JvmtiTagMap :: do_weak_oops ,它的确对所有标签进行了迭代, 并对所有标签进行了一些不太便宜的操作。 更糟的是,该操作是顺序执行的,并且不并行执行。 在每个垃圾回收之后找到调用此方法的调用链之后,解决了最后一个难题。 (为什么这样做的方式以及它与弱引用的关系完全超出了本文的范围)

在并行GC上运行并具有与串行运行相同的昂贵操作,一开始似乎是设计缺陷。 第二个想法,JVMTI的创建者可能从未期望有人标记所有的堆,因此从来没有费心去优化此操作或并行运行它。 毕竟,您永远无法预测人们将使用您设计的功能的所有方式,因此也许值得检查Hotspot中的GC后活动是否也应该有机会使用现代JVM倾向于使用的所有gazillion内核。可使用。

因此,为了解决这个问题,我们需要清理不再需要的标签。 修复它就像在我们的JVMTI回调之一中仅添加三行一样容易:

+  if(isGenerated(*tag_ptr)) {
+    *tag_ptr = 0;
+  }

瞧,一旦分析完成,我们几乎和开始时一样出色。 如下面的屏幕截图所示,在发现内存泄漏期间仍然存在暂时的性能波动,并且在完成内存泄漏分析之后会略有恶化:

gc-pause-short

结语

现在,补丁已推出,并且解决了Plumbr检测到泄漏后GC暂停时间受到影响的情况。 随意去获取更新的代理以解决性能问题。

作为一个总结,我建议您在使用广泛的标签时要格外小心,因为“便宜”的标签会堆积在角落的箱子上,从而为性能的大幅下降奠定了基石。 为确保您没有滥用标记,请翻转– XX:+ TraceJVMTIObjectTagging的诊断选项。 它将使您能够估计标签映射消耗多少本机内存以及堆遍历花费的时间。

翻译自: https://www.javacodegeeks.com/2015/02/jvmti-tagging-can-affect-gc-pauses.html

jvmti

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

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

相关文章

C语言-使用goto语句从循环中跳出

实例代码// //实现功能:使用goto语句从循环中跳出 //#include "stdio.h"#define EXIT 0void show_Menu(){printf("菜单选项:\t");printf("1:显示\t");printf("2:添加\t");printf("3&#xff1a…

装饰器模式java_Java 8的装饰器模式

装饰器模式java在最近的一篇文章中,我描述了装饰器模式如何挽救了我的一天。 我给出了一个小代码段,其中包含创建装饰器的最简单方法,但承诺Java 8会有更好的方法。 这里是: 用Java 8装饰 HyperlinkListener listener this::ch…

C语言-反转字符串

实例代码// //实现功能&#xff1a;输入一个字符串&#xff0c;然后将该字符串反向输出 //#include "stdio.h" #include "string.h"#define N 50void convert_str(char str[N]);void convert_str(char str[N]){int j;char temp;for (int i 0; i < strl…

信捷步进指令的使用_步进电机驱动器的模式

步进电动机和步进电动机驱动器构成步进电机驱动系统。步进电动机驱动系统的性能&#xff0c;不但取决于步进电动机自身的性能&#xff0c;也取决于步进电动机驱动器的优劣。对步进电动机驱动器的研究几乎是与步进电动机的研究同步进行的。步进电机驱动器有三种基本的步进电机驱…

C语言灵魂篇|指针作为函数返回值

C语言允许函数的返回值是一个指针&#xff08;地址&#xff09;&#xff0c;我们将这样的函数称为指针函数。下面的例子定义了一个函数 strlong()&#xff0c;用来返回两个字符串中较长的一个&#xff1a;#include #includechar *strlong(char *str1, char *str2){ if(strlen(s…

css 样式尾部带感叹号是什么意思_CSS书写规范

推荐大家看看百度FEX前端团队和腾讯AlloyTeam前端团队的CSS代码规范。fex-team/styleguide​github.comCode Guide by AlloyTeam​alloyteam.github.io1. 样式属性顺序单个样式规则下的属性在书写时&#xff0c;应按功能进行分组&#xff0c;组之间需要有一个空行。同时要以Pos…

C语言精髓篇|函数的参数和返回值

如果把函数比喻成一台机器&#xff0c;那么参数就是原材料&#xff0c;返回值就是最终产品&#xff1b;从一定程度上讲&#xff0c;函数的作用就是根据不同的参数产生不同的返回值。函数的参数在函数定义中出现的参数可以看做是一个占位符&#xff0c;它没有数据&#xff0c;只…

oc引导win方法_[OC更新]机械革命X1/X6TIS标压测试版更新

加关注这种话银家怎么好意思说出口嘛更新机型机械革命X1 i5-7300hq机械革命X1 i7-7700hq机械革命X6tis i5-7300hq机械革命X6tis i7-7700hq更新内容基于OC0.6.2 MOD版本编译修复WIN下电脑被识别为MBP导致电竞中心打不开问题修复INTEL网卡在BIG SUR下不识别问题禁用secureboot mo…

java 打开gc日志_在运行时打开GC日志记录

java 打开gc日志总是有下一个JVM表现不佳。 而且&#xff0c;您内心深知&#xff0c;如果您只有少数启动选项可以公开一些有关正在发生的事情的信息&#xff0c;那么您可能就有机会真正修复该死的东西。 但是不&#xff0c;您需要的标志&#xff08; -XX&#xff1a; HeapDumpO…

C 和C语言条件运算符的区别

条件运算符&#xff08;conditional operator&#xff09;有时候也称为三元运算符&#xff08;ternary operator&#xff0c;或者trinary operator&#xff09;&#xff0c;因为它是唯一需要 3 个操作数的运算符&#xff1a;条件 ? 表达式1 : 表达式2条件运算操作会首先计算条…

C 运算符和语句总结

运算符&#xff1a; C 表达式中的左值和右值&#xff1a;当一个对象被用作左值时&#xff0c;用的是对象的身份&#xff08;内存中的位置&#xff09;。当作为右值时&#xff0c;用的是对象的值&#xff08;内容&#xff09;。或者说&#xff0c;lvalue:具有存贮性质的对象&…

# 遍历结构体_C#学习笔记05--枚举/结构体

一.枚举当变量的取值范围是固定的几个, 例如性别--男,女; 英雄类型 -- 法师, 刺客.战士, 射手等等. 这时就可以使用枚举类型, 会更加简洁方便.1.1.定义:访问修饰符 enum 枚举类型名 {成员1,成员2,成员3,... }public enum Days{Mon 1,Tue,Wed,Thu,Fri,Sat,Sun}enum: 是枚举的…

C语言中枚举enum的用法

本文举例说明C语言中enum枚举关键字的用法。用来同时定义多个常量利用enum定义月份的例子如下。#include enum week {Mon1,Tue,Wed,Thu,Fri,Sat,Sun}; int main() {printf("%d",Tue); return 0; }这样定义Mon的值为1之后&#xff0c;Tue的值就被默认定义为2&#…

苹果更新未知错误17_iOS 13 新功能,静音未知来电

果粉俱乐部让科技更好的服务生活点击上方「蓝字」加入我们iOS 13 正式版系统已经推出了快三周时间&#xff0c;苹果在新系统当中带来了诸多功能改进&#xff0c;包括大家盼望已久的深色模式&#xff0c;新的音量调节设置&#xff0c;自定义流量下载限制等等。除此之外&#xff…

C/C 语言中extern的用法

声明外部变量现代编译器一般采用按文件编译的方式&#xff0c;因此在编译时&#xff0c;各个文件中定义的全局变量是互相透明的&#xff0c;也就是说&#xff0c;在编译时&#xff0c;全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程&#xff0c;里面含有…

设置公共请求参数_封装一个useFetch实现页面销毁取消请求

前端业务经常会出现这样一类问题&#xff0c;当用户网速过慢或是其他特殊情况下&#xff0c;该页面的请求还未完成&#xff0c;用户就已经点击其他页面跳出去了。理想状态下请求也是应该终止掉的&#xff0c;所以我们应该想办法将请求和页面卸载关联在一起。1 使用AbortControl…

C语言中return的各种用法

按初学的理解&#xff0c;return的任务就是返回对应的参数&#xff0c;在外层函数中对这个参数做进一步处理。实际上return的用法不只这些。为调用的函数返回参数值此类应用最为普遍&#xff0c;通常是在一个具有返回值的函数中&#xff0c;返回一个参数值&#xff0c;这个返回…

代码内查找函数引用_叮~~二级操作题 excel常考函数大梳理

1.AND函数格式&#xff1a;AND(logical1,logical2…)功能&#xff1a;and函数是一个逻辑函数&#xff0c;表示同时满足多个条件。通常配合if函数做条件判断&#xff0c;得值为true或者是false。2.OR函数格式&#xff1a;OR(logical1,logical2…)功能&#xff1a;or函数是一个逻…

总结C语言中的数组知识点

数组&#xff1a;只能存放一种数据类型&#xff0c;比如int类型的数组、float类型的数组&#xff0c;里面存放的数据称为“元素”。数组的定义&#xff1a;首先声明数组的类型&#xff0c;然后声明数组元素的个数&#xff0c;也就是定义需要多少存储空间。数组格式与初始化格式…

主要矛盾和次要矛盾_次要GC,主要GC与完整GC

主要矛盾和次要矛盾在使用Plumbr中的GC暂停检测功能时&#xff0c;我被迫通过大量有关该主题的文章&#xff0c;书籍和演示工作。 在整个旅程中&#xff0c;我多次对次要&#xff0c;主要和完全GC事件的使用&#xff08;误用&#xff09;感到困惑。 这导致了这篇博客文章&#…