当前位置: 首页 > news >正文

JVM实战(15)——Full GC调优

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析

阶段4、深入jdk其余源码解析

阶段5、深入jvm源码解析

一、简介

本章将会讲解一个频繁Full GC的案例,示例来自于JVM基础篇中的亿级流量系统。我们先来回顾下案例。

1.1 案例背景

假设现在生产环境有一套“数据计算系统”,不停地从MySQL等各类数据源提取数据到内存中进行计算,系统是分布式的。

每个节点(机器)每分钟执行100次操作(提取数据并计算,每次操作耗时10s),每次操作1万条数据,每条数据大小为1KB左右,每次操作的数据大小就是10MB:

每台机器的配置是4核8G,JVM分配4G内存,其中新生代1.5G,老年代1.5G。

1.2 内存使用模型估算

每次操作会在Eden区分配10MB对象,以1分钟100次操作来算,那么Eden区1分钟内就会被占满:

二、Full GC调优

每个计算任务处理1万条数据耗时10s,假设此时80个计算任务都结束了,还有20个计算任务共计200MB正在计算中,那么此时200MB对象是存活的,不会被Young GC回收掉:

2.1 扩Survivor

由于任何一块Survivor区只有100MB,所以新生代中这存活的200MB对象会晋升到老年代,然后清空Eden:

如此反复,大约经过7分钟后,也就是经历了7次Young GC,此时大概有1.4G对象在老年代中:

再经过1分钟,也就是第8分钟结束时,新生代又满了,此时发现老年代可用空间已经不足(剩余100MB),比历代平均的晋升对象大小(200MB)要小,所以会直接触发一次Full GC。

Full GC会先把老年代的垃圾回收了(假设能全部回收),然后执行一次Young GC,此时Eden区存活的对象会进入老年代:

按照这种情况,每隔8分钟左右就会发生一次Full GC。Full GC的性能是很差的,所以必须进行优化,最基本的优化思路就是扩大Survivor区的内存,比如扩到200MB。这样基本就能避免对象频繁进入老年代,将Full GC频率降低到几个小时一次。

2.2 采用大内存

上述的示例,是假设系统每天的负载是1亿请求, 如果请求量再扩大十倍呢?

参照首节的内存使用模型来估算, 每秒中会有100MB左右的数据进入Eden,那么Eden会在10s内就被塞满,触发Young GC 。

计算任务本身就耗时10s左右,所以直接后果就是,即使进行了Young GC,可能也只能回收掉几百MB数据。那每隔10s,就有1G左右的数据进入老年代,那下一个10s又来1G数据,就会触发Full GC。最终的结果就是每分钟触发好几次Full GC,对于系统来说就是灾难。

所以,针对这个问题,首先要做的显然就是扩内存,比如换成16核32G的机器,Eden分配16G,Survivor各分配2G。那么按每秒加载100MB数据进内存来算,需要2分钟左右才会触发一次YoungGC,而每次Young GC的存活对象也就是几百MB,Survivor区足够容纳。这就避免了对象频繁进入老年代,触发Full GC。

那么,针对这种大内存的机器,我们是否需要用G1作为垃圾回收器呢?

对于本示例中的系统是不需要的,因为这种数据计算系统一般都是离线的,也就是说不和用户直接交互,所以哪怕每隔2分钟进行一次Young GC,每次Young GC耗时1s也没什么影响。

相关文章:

  • uniapp 编译后文字乱码的解决方案
  • Ps:何时需要转换为智能对象
  • 招投标系统是Electron的纯内网编辑Office Word,可以设置部分区域可编辑,其他的地方不能编辑吗?
  • MyBatis第三课
  • day-09 删除排序链表中的重复元素
  • GAMES101:作业7记录
  • 【Go】excelize库实现excel导入导出封装(三),基于excel模板导出excel
  • Linux shell编程学习笔记39:df命令
  • Go语言使用gosseract 库来进行图像文字识别,识别出来的中文是乱码的?如何解决?
  • linux项目部署(jdk,tomcat,mysql,nginx,redis)
  • python学习笔记10(选择结构2、循环结构1)
  • 【Linux】Linux系统编程——Linux目录结构
  • 【驱动】TI AM437x(内核调试-02):dynamic 动态打印调试
  • 微信小程序Canvas画布绘制图片、文字、矩形、(椭)圆、直线
  • Spring整理-Spring框架的国际化
  • 分享的文章《人生如棋》
  • 【Leetcode】104. 二叉树的最大深度
  • 【知识碎片】第三方登录弹窗效果
  • cookie和session
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • javascript 哈希表
  • JavaScript学习总结——原型
  • JWT究竟是什么呢?
  • Linux中的硬链接与软链接
  • mysql外键的使用
  • Redis的resp协议
  • TCP拥塞控制
  • vagrant 添加本地 box 安装 laravel homestead
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • Windows Containers 大冒险: 容器网络
  • 初识 webpack
  • 规范化安全开发 KOA 手脚架
  • 使用agvtool更改app version/build
  • 主流的CSS水平和垂直居中技术大全
  • Linux权限管理(week1_day5)--技术流ken
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #window11设置系统变量#
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (09)Hive——CTE 公共表达式
  • (12)Hive调优——count distinct去重优化
  • (bean配置类的注解开发)学习Spring的第十三天
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .gitattributes 文件
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET Core 版本不支持的问题
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .Net Memory Profiler的使用举例