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

【JVM】亿级流量调优(二)

亿级流量调优

指针压缩

-XX:-UseCompressedOops指针压缩技术只有64位机器才有。jdk6以后引入的技术,默认是开启的

关闭指针压缩的情况下

在这里插入图片描述
在这里插入图片描述

通过HSDB用Memory Viewer查看该对象在内存中的分配地址发现类型指针占8字节,0x3其实是数组的长度,前面用一行来存储类型指针

开启指针压缩的情况下

在这里插入图片描述
在这里插入图片描述
通过HSDB用Memory Viewer查看该对象在内存中的分配地址发现类型指针占4个字节,开启之后,类型指针和数组长度放在一起了

上面的情况分析如下:

在这里插入图片描述

跟C/C++中的一个联合体有关联

union u {
int i;  // 4B
void p; // 8B
}

该联合体所占大小由最大字节数决定
比如说类型指针:0xffffffff,数组长度为0x00000003,当开启指针压缩时,由于只使用了联合体中的4B,但是联合体本身还是占8B,于是就出现了4B的浪费情况,数组长度占4B,那么把两者拼在一起,就可以节省8B的开销,把数组长度填充到前4B里面,相当于0x0003ffff。

为什么数组对象在关闭指针压缩的情况下有两段填充?不仅要站在学习者的角度去思考问题,更要以设计者的角度去思考

在这里插入图片描述

  • 1.在开启指针压缩的情况下:
    类型指针0xffffffff 8B
    数组长度:0xffff 4B
    用一个8B就存储下了
  • 2.那么在关闭指针压缩的情况下
    类型指针0xffffffff 8B
    数组长度: 0x0000ffff
    由于数组长度只占4B,根据8字节对齐的规范,对于一行内存地址来说,这里就出现了4字节的空间,那么我们知道,数组长度的下一个数据区域就是实例数据,如果说实例数据中正好有一个int类型,那么ok,正好填补到前面的4个字节里面,那如果不是int类型呢?是char类型的呢?虽然说可以存进去,但是作为设计者如何知道这个数据区域存储的实例数据是char类型还是int类型呢?所以说,存进去的话,会比较麻烦,于是需要在对象头的尾部进行对齐填充

指针压缩的底层原理?这个技术能被开发出来归根结底是来自"所有对象大小都必须能被8整除"这条规则。

在这里插入图片描述

8字节对齐的言外之意 8(1 000)
如图所示,现在有三个对象
test1:16B
test2:32B
test3:24B

test1的起始地址: 0B
test2的起始地址:16B
test3的起始地址:48B
他们分别对应的二进制:
test1: 0 000
test2:10 000
test3:110 000
可以看到后三位永远是0,那么JVM在存储的时候,就可以这样存储,向右移3位。>>3
也就是说只存储
test1: 0
test2: 10
test3: 110
然后在使用的时候可以左移3位, << 3,再把它还原回去
根本原因在于"8字节对齐"这条规则

堆内存的32G瓶颈从何而来?

在32位机器中,最大内存可以表示为4G,现在机器普遍已经是64位了,按理说,堆内存可以设置超常的大,为什么还会有32G这个瓶颈之说呢?
原因在于,2的32次方表示的内存为4G,在指针压缩使用时,可以将低位进行左移3位,可表示的最大内存也就是2的35次方=32G.

如何扩容,思路是什么?为什么是8字节对齐?

要突破32G内存瓶颈的话,需要改写8字节对齐这条规则,8字节对齐的话,瓶颈是32G,16字节对齐,瓶颈也会扩大一倍,变成64G.但是这样需要考虑内存的使用率,因为在对齐填充的时候,补充的都是空白地址,也就是说在突破瓶颈的同时,也会带来内存空间的浪费。
现在64位机器,并没有完全使用64位地址来表示,只使用了48位,剩下16位保留。也就是说,64位机器上最大使用的内存是2的48次方,原因在于CPU还没有强大到能处理这么大的内存,受制于CPU的算力

例如:
8字节对齐:17B+7B=24B
16字节对齐:17B +15B= 32B(内存的浪费可能更严重)
另外还有一部分原因是:
32G的内存,那么OOM的Dump文件将会变得非常大,普通机器将没法分析

对于一个正常的GC来说,它的频率应该是
5分钟一次YGC
1天一次FullGC
内存大了,虽然发生FullGC的频率小了,但是单次GC花费的时间更长了

JVM调优

为什么调优?
调优的顺序:避免OOM>FullGC>YGC

  • 1.避免OOM,
  • 2.尽可能减少FullGC,FullGC会引发STW(Stop The World)
    到底调什么?
  • 1.在项目部署到线上之前,基于可能的并发量进行预估调优
  • 2.,在项目运行过程中,部署监控收集性能数据,平时分析日志进行调优
  • 3.线上出现OOM,进行问题排查与调优

实战:亿级流量系统实战

在这里插入图片描述

  • 1.如果每个用户平均访问20个商品详情页,那访客数约定于500w(一亿/20)
  • 2.如果按转化率10%来算,那日均订单约等于50w(500w * 10%)
  • 3.如果30%的订单是在秒杀前两分钟完成的,那么每秒产生1200笔订单(50w*30%/120s)
  • 4.订单支付又涉及到发起支付流程、物流、优惠券、推荐、积分等环节,导致产生大量对象,这里我们假设整个支付流程生成的对象为20K,那么每秒在Eden区生成的对象约等于20M(1200笔 * 20K)
  • 5.在生产环境中,订单模块还涉及到百万商家查询订单、改价、包邮、发货等其他操作,又会产生大量对象,我们放大10倍,即每秒在Eden区生成的对象约等于200M(其实这里就是在大并发时刻可以考虑服务降级的地方,架构其实就是取舍)
    假设响应一个请求的时间为3s(包括付款、扣减库存)
    这里的假设数据都是大部分电商系统的通用概率,是有一定代表性的.如果你作为这个系统的架构师,面对这样的场景,你会如何做JVM调优呢?即将运行该系统的JVM堆区设置成多大呢?

分析:

  • 1.每秒产生200M对象,Eden区的大小为2.2G,相当于11s就会触发YGC(11 x 200 = 2200M对象),由于假设一个请求响应时间为3s,所以发生GC的时候,会有600M(200M * 3 = 600M)对象回收不掉。GC回收的是标记不到的对象,而S0、S1只有270M,放不下这600M对象,进而触发老年代空间担保机制,放入老年代。对于老年代而言,大小为5400M->9次YGC->触发一次FGC.9x11=99s,触发一次FC,这样的频率8G内存不适合的
  • 2.怎么做调优?加内存?怎么加?
    S0、S1的内存区域要大于600M,这样,假设S0/S1都为600M,Eden区为4800M(600 x 8 = 4800),约等于6G,那老年代为12G(6G x 2 = 12G),内存加起来的话,12G+6G=18G,但是内存一般都取2的n次幂,所以取16G即可。

如果不调优,则会出现一直触发FGC,又回收不到可用的内存,进而导致JVM发生崩溃

1.堆到底设置成多大比较合适?堆越大越好吗?

如果堆设置的很小-> GC频率可能很高,GC时间也比较短
设置的很大->GC频率会低,但是GC的时长却增加了
调优不是一蹴而就的,需要逐步调整,并观察JVM的GC情况
2.什么样的系统可以进行JVM调优?
首先要区分出是OLAP(在线分析)系统还是OLTP(在线事务查询)系统,如果是OLAP(在线分析)系统,是没有多大调优空间的,因为一次性要查询大量对象,这个是没有办法做调优的,只能加大内存
3.正常GC单次时长100ms,前端和后端的平衡,不能让前端感到明显卡顿

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Linux 下命令行参数和环境变量
  • vue3+ts+Go使用百度地图路书实现历史轨迹回放、轨迹回放进度、聚合点、自定义弹框和实时监控视频、多路视频轮巡播放
  • 【大数据算法】一文掌握大数据算法之:排序链表搜索的亚线性算法。
  • 服务容错(Service Fault Tolerance)
  • Git 版本控制操作
  • 鲲鹏服务器安装Kafka
  • C#二叉搜索树算法
  • 数据库查询优化:提高数据提取效率
  • 趋势分享|Gartner解读中国企业容器管理新挑战:混合环境、容器安全、AI支持
  • 网络缓存:加速网络应用的隐形引擎
  • 如何在 Ubuntu 系统中安装PyCharm集成开发环境?
  • Java—Arrays api
  • P2730 [USACO3.2] 魔板 Magic Squares
  • 今日总结:巧用setTimeout()方法来制造局部刷新效果
  • MySQL学习笔记之用户管理与权限控制(DCL)
  • $translatePartialLoader加载失败及解决方式
  • egg(89)--egg之redis的发布和订阅
  • extjs4学习之配置
  • Java到底能干嘛?
  • js数组之filter
  • Laravel 菜鸟晋级之路
  • mysql常用命令汇总
  • Next.js之基础概念(二)
  • PAT A1120
  • v-if和v-for连用出现的问题
  • Vue--数据传输
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 测试如何在敏捷团队中工作?
  • 分类模型——Logistics Regression
  • 那些被忽略的 JavaScript 数组方法细节
  • 学习Vue.js的五个小例子
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #ifdef 的技巧用法
  • #pragma pack(1)
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (8)STL算法之替换
  • (Forward) Music Player: From UI Proposal to Code
  • (Git) gitignore基础使用
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (六)Flink 窗口计算
  • (数据大屏)(Hadoop)基于SSM框架的学院校友管理系统的设计与实现+文档
  • (学习总结16)C++模版2
  • (一)u-boot-nand.bin的下载
  • (转载)利用webkit抓取动态网页和链接