看elasticsearch官方文档时,提到的一个观点:Don’t Cross 32 GB。是因为当JVM堆少于32G时,HotSpot虚拟机会启用一个压缩对象指针。而如果超过32G,这个压缩对象指针就会失效。那么,究竟这个临界值的精确值是多大呢?开启压缩指针相比没有开启,能节省多少内存呢?让我们一探究竟!

Don’t Cross 32 GB!

在Java的世界里,绝大部分对象分配在堆里,并且被一个指针引用(Student stu = new Student(),new的这个Student对象就是分配在堆里,stu就是持有这个对象的应用)。

32位的操作系统,最大只支持4G内存(即2^32)。当然,对于当下来说,32位服务器应该是绝种了,所以本文讨论的是64位操作系统。对于64位操作系统来说,理论上分配的堆可以非常非常大。但是,64位指针的开销就意味着有更多的浪费空间,这仅仅是因为指针更大。比浪费空间更糟糕的是,64位指针在主内存和多级缓存之间移动数据的时候,还会消费更多的带宽。

Java用"compressed oops"术解决了这个问题,指针不再是指向内存中精确位置,而是对象的偏移量(原文: Instead of pointing at exact byte locations in memory, the pointers reference object offsets)。这就意味着,32位指针能引用2^32 个对象(大约43亿个对象),而不是引用总计2^32 个字节大小对象。所以,堆大小直到32G左右还能保持32位指针。

一旦你越过这个32G--一个具有魔法般的数值。指针将切回到普通的对象指针。每个指针变大,意味着需要更多的CPU,内存和带宽,真正用来保持对象的内存就会更少。这就可能导致一种奇怪的现象,使用compressed oops的32G的堆和40~50G没有使用compressed oops的堆保存的对象数量是一样的。

这个事实告诉我们:即使你有多余的内存,也应该尽量避免超过32G这个界限。它会浪费内存,降低CPU性能,并且大堆情况下GC表现也一般般。更麻烦的是,那么大的堆,DUMP分析将是一件极其痛苦,极其麻烦的事情。相信我,你一定不想碰到那种局面。

应该设置多大?

32G是个近似值,这个临界值跟JVM和平台有关。如果不想精确设置的话,31G是个决定安全的数值,31G肯定默认开启compressed oops。我们可以通过增加JVM参数-XX:+PrintFlagsFinal,验证UseCompressedOops的值,从而得知,到底是不是真的开启了压缩指针,还是压缩指针失效!

实践才是检验真理的唯一标准!JUST DO IT!让我们动手验证这个临界值吧!

验证情况--JDK8前提下,32760m的堆是开启压缩指针的,32770m的堆压缩指针已经关闭:

[afei@afei ~]$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)[afei@afei ~]$ java -Xmx32760m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOopsbool UseCompressedOops                        := true                                {lp64_product}
[afei@afei ~]$ java -Xmx32770m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOopsbool UseCompressedOops                         = false                               {lp64_product}

32G,即32*1024=32768M,刚好在范围[32760, 32770]中。

土豪我有1T内存

JVM大堆的缺点太多了;

  • 超过32G压缩指针失效;
  • DUMP分析将是灾难;
  • 堆越大,GC表现越差;

总之,不要尝试吃这个螃蟹!那如果我是在一家有钱任性的公司,服务器牛逼的不要不要的,都是128G起步!毕竟不要让贫穷限制了想象!

这种情况下,我有小建议:开多个32G的JVM实例。4个32G的JVM实例绝对比1个128G实例表现要好。

简单测试验证

笔者做了一个简单测试,验证一下这个问题:分配设置Xmx为Xmx32760mXmx32770m,Xmn都是100M(S0:S1:Eden默认1:1:8)。总计分配一个包含8个对象类型和8个原子类型以及String,总计17个类型属性的对象1kw次。看它们分别触发了多少YGC,结论如下表所示:

实验次数 开启压缩指针YGC次数 关闭压缩指针YGC次数
1 17.53 21.91
2 17.54 21.92
3 17.52 21.94

由执行结果可知,Young区完全一样的情况下,开启压缩指针相比关闭压缩指针,能节省20%多的内存。由此可知,32G还真是一个奇妙的魔法数值!另外需要说明的是YGC次数有小数,是表示Eden区占用比例,比如17.52次YGC表示发生了17次YGC并且Eden还占了52%。

执行的命令:

java -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xmx32770m -Xms32770m -Xmn100m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseCMSInitiatingOccupancyOnly Test

说明:-Xmx32760m -Xms32760m即表示开启压缩指针;-Xmx32770m -Xms32770m即表示关闭压缩指针。

  • 附:测试源码
/*** @author wangzhenfei* @date 2018-09-05* @since 1.0.0*/
class Student{private byte a;private short b;private int c;private long d;private float e;private double f;private boolean g;private char h;private Byte i;private Short j;private Integer k;private Long l;private Float m;private Double n;private Boolean o;private Character p;private String q;// 省略带参数构造方法
}
public class Test {public static void main(String[] args) throws Exception{for (int i = 0; i < 10000000; i++) {Student stu = new Student((byte)(i%128), (short)(i%256), i, i, i, i, i%2==0?true:false, 'a',(byte)(i%128), (short)(i%256), i, (long)i, (float)i, (double)i, i%2==0?Boolean.TRUE:Boolean.FALSE, 'a', String.valueOf(i));if(i>0 && i%100000==0){System.out.println("i="+i);}}// 留点时间采集GC信息Thread.sleep(20000);}
}

参考:https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html

Don’t Cross 32 GB!相关推荐

  1. elasticsearch优化总结

    一. 硬件环境选择: 如果有条件,尽可能使用SSD硬盘, 不错的CPU.ES的厉害之处在于ES本身的分布式架构以及lucene的特性.IO的提升,会极大改进ES的速度和性能. 二.系统拓朴设计: ES ...

  2. 弃用 32 位!所有基于 IntelliJ 的 IDE 将不再支持 32 位操作系统

    整理 | 苏宓 出品 | CSDN(ID:CSDNnews) 近日,JetBrain 宣布旗下所有基于 IntelliJ 的 IDE 将停止支持 32 位操作系统,其中包括 AppCode.Clion ...

  3. 32位/64位WIN2003各版本支持内存列表 彻底解决XP系统无法支持4G内存的问题

    WIDOWS2003各版本支持内存简表 版本  支持CPU数量  支持最大内存  32位 Windows Server 2003, Standard Edition (标准版)  2路  4G  32 ...

  4. 配置 SQL Server 以便使用 2 GB 以上的物理内存

    配置 SQL Server 以便使用 2 GB 以上的物理内存 [@more@]1. 概要 ??使用Windows 2000 Server 的操作系统,对于SQL Server而言,需要打开操作系统的 ...

  5. 32位系统的X86到底能支持多大内存

    微软最新Windows Server 2008 R2 \ 以及最新的Microsoft Office SharePoint ( MOSS ) 2010 \ Project Server 2010 \ ...

  6. 读文章笔记-自适应和加速GB生成算法

    读文章笔记-GBC 文章 背景 内容 定义1+现有GB生成过程 GBKNN 文章的GB生成算法 疑问与反思 文献脉络 文章 An Efficient and Adaptive Granular-Bal ...

  7. 戴尔(Dell)G3 3579(128 GB 固态硬盘+1 TB 机械硬盘)安装Ubuntu 16.04 LTS单系统(不是双系统,只装Ubuntu)

    Table of Contents 硬件: 目标: 步骤: 1. 关于系统盘(在另外一台机子上操作U盘文件) 2. BIOS设置 3.安装系统 4. 安装完成后注意事项 5. 附安装过程中遇到的错误( ...

  8. NVIDIA GPUs上深度学习推荐模型的优化

    NVIDIA GPUs上深度学习推荐模型的优化 Optimizing the Deep Learning Recommendation Model on NVIDIA GPUs 推荐系统帮助人在成倍增 ...

  9. Machine learning strategies for systems with invariance properties( 具有不变性系统的机器学习策略 )2016年Julia Ling

    目录 摘要 1.介绍 2.方法 2.1不变基的结构 2.2建立机器学习模型 2.3机器学习算法 3.研究案例 3.1.湍流模型案例研究 3.1.1.问题阐述 3.1.2.不变性 3.1.3.数据集 3 ...

最新文章

  1. OpenStack Nova 高性能虚拟机之 CPU 绑定
  2. 【组合数学】指数生成函数 ( 指数生成函数求解多重集排列示例 )
  3. Java集合源码分析(二)ArrayList
  4. PhpMyAdmin导入数据库大小限制?
  5. java实现word邮件合并,Aspose.Words控件操作实例—邮件合并功能概述
  6. (6)段描述符D/B位
  7. 【网络安全】Penelope:一款功能强大的Shell处理工具
  8. vue 实现返回上一页不请求数据keep-alive
  9. ERROR org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode: Exception in doCheckpoint
  10. 常用有话帧检测技术(VAD)
  11. C++定义隐式转换函数,将类转换为内部的一个成员变量
  12. Java编程思想 学习笔记1
  13. P1829 [国家集训队]Crash的数字表格(推了好久的mobius反演)
  14. Android 功耗优化(3)---Android后台调度与省电
  15. html无需列表怎么打,如何以html无序列表形式而不是xml打印这些结果?
  16. Python 下的 lambda 算子
  17. Java annotation 自定义注释@interface的用法 转载记录
  18. mysql 数据类型总结
  19. [书籍翻译]12周撰写期刊文章 学术出版成功指南——第 4 周:选择期刊
  20. 手机APP测试类型与方法

热门文章

  1. PHP 实现大数据(30w量级)表格导出(导出excel) 提高效率,减少内存消耗,终极解决方案
  2. 利用python re提取文件中的块内容(多行)
  3. unity沙子堆积_unity游戏逼真沙子和白雪粒子特效渲染创建插件Basic Sand amp; Snow 1.0 - 素材巷...
  4. Linux设置U盘加密,制作Kali Linux 加密U盘启动盘
  5. Go语言段子爬虫--捧腹网
  6. 企业生产发展从第一次工业革命到信息化时代
  7. 发票识别+发票查验API、发票管理效率
  8. vsCode 快捷键PDF
  9. 谷歌浏览器单独下载插件文件crx到本地的方法步骤
  10. oracle添加索引指定表空间,Oracle 创建索引表空间语法-oracle