JVM堆外内存泄漏故障排查记录
新生代gc如何优化? 对于G1而言,我们首先应该给整个JVM的堆区域足够的内存,其次就是给新生代足够的内存,保证:
之前我们算过,这个系统每分钟会有 550mb 的对象会进入新生代 , 4.5s 就会来一次 ygc , 一分钟会有 13 次左右的 gc , 每次 gc 大概在 200ms 以内。 PS : G1 回收只有初始标记和重新标记的阶段是 stw,其他阶段都是并发的, gc 200ms , 真正 stw 的时间可能只是 几十 ~ 一百ms 不过!每分钟 13次 的 ygc 频率,每次接近 200ms 左右耗时 gc 效率实在太低了 新生代优化 因为有 记忆集 (RSet) 的存在,在 G1 回收 Region 效率不变的情况下 , 优化的点就来了 扩大每个 Region 的大小 , 也就是扩大堆内存的大小 , 简而言之就是升级机器的内存 或者是 集群进行扩容增加服务器的数量 目前这个业务系统只有 32 台机器 8C 16G的机器 , 给堆空间的大小只有 12G , 对亿级的流量还是不太能抗住 , 目前阶段性的分析后 , 性能瓶颈不在 CPU , 我们只需要升级内存即可 升级到 8C 32G 给堆 24~26G 的空间 , 元空间给 1G 则机器数量不变 升级到 16C 64G 给堆 58~60G 的空间 , 元空间给 1G 还可以下几台机器 为什么会发生 Mixed gc ? 对于 Mixed gc 的触发,大家都知道是老年代在堆内存里占比超过 45% 就会触发 再回顾一下:年轻代的对象进入老年代的几个条件:
其中尤其关键的是新生代 gc 过后存活对象过多无法放入 Survivor 区域 , 以及动态年龄判定规则这两个条件尤其可能 让很多对象快速进入老年代 一旦老年代频繁达到占用堆内存 45% 的阈值 , 那么就会频繁触发 Mixed gc 那我们的目标就是 : 尽量避免对象过快进入老年代 , 尽量避免频繁触发 mixed gc , 就可以做到根本上优化 mixed gc 了 Mixed gc 优化思路 Mixed gc 优化的核心还是 -XX:MaxGCPauseMills 这个参数 大家可以想一下 , 假设 -XX:MaxGCPauseMills 参数设置的值很大 , 导致系统运行很久 新生代可能都占用了堆内存的 70% 了 , 此时才触发新生代 gc 那么存活下来的对象可能就会很多 , 此时就会导致 Survivor 区域放不下那么多的对象 , 就会进入老年代中 或者是新生代 gc 过后 , 存活下来的对象过多 , 导致进入 Survivor 区域后触发了动态年龄判定规则 达到了 Survivor 区域的 50% , 也会快速导致一些对象进入老年代 所以这里核心还是在于调节 -XX:MaxGCPauseMills 这个参数的值 , 在保证新生代 gc 别太频繁的同时 , 还得考虑每次 gc 过后的存活对象有多少 避免存活对象太多快速进入老年代,频繁触发 Mixed gc 五、实际有效的调优参数 1.-XX:MaxGCPauseMillis: 根据系统可以接受的响应时长和指标 观察 JVM 的回收时间来进行修改 单位:ms 太小跟不上分配内存的速度 , 太大 gc 的时间太长。 2.-XX:ParallelGCThreads: 在 stw 阶段工作的 GC 线程数 , 可以根据当前机器 CPU 核数来设置 , 建议核心数 -1 -XX:ConcGCThreads: 在非 stw 阶段工作的 GC 线程数 , 会影响系统的吞吐量 , 毕竟是要跟用户线程抢 CPU 资源 系统如果是计算密集型的建议是 CPU 核数的 1/4 ~ 1/3 , iO 密集型建议是 1/2 3.-XX:G1ReservePercent: G1为分配担保预留的空间比例 也就是老年代留多少空间给 新生代来晋升 , 默认是 10% 如果晋升失败会触发单线程的 old gc 非常恐怖 , 建议高并发系统加大机器内存 提高这个参数的比例
4.-XX:MaxMetaspaceSize: 元空间最大大小 , 在高并发且机器内存够的情况 建议增大元空间的大小 (编辑:济宁站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |