64g内存服务器+jvm参数?jvm 优化篇-(8)-跨代引用问题(RememberSet、CardTable、ModUnionTable、DirtyCard)

:暂无数据 2026-07-18 06:50:02 1

64g内存服务器+jvm参数?jvm 优化篇-(8)-跨代引用问题(RememberSet、CardTable、ModUnionTable、DirtyCard)

今天给各位分享64g内存服务器+jvm参数的知识,其中也会对64g内存服务器+jvm参数进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录

64g内存服务器+jvm参数

如果你的服务器有 64GB 内存,你可以使用以下 JVM 参数来优化 Java 程序的性能:

  • -Xmx:设置 Java 堆的最大内存使用量。推荐将该参数设置为总内存的 50% 到 80%。例如,可以设置为 -Xmx48g,表示 Java 堆最大可使用 48GB 内存。

  • -Xms:设置 Java 堆的初始内存使用量。推荐将该参数设置为总内存的 25% 到 50%。例如,可以设置为 -Xms16g,表示 Java 堆初始使用 16GB 内存。

  • -Xmn:设置新生代的内存使用量。推荐将该参数设置为 Java 堆的 1/4 到 1/3。例如,可以设置为 -Xmn16g,表示新生代使用 16GB 内存。

  • -XX:+UseG1GC:使用 G1 垃圾收集器,它是一种面向服务端应用的垃圾收集器,能够高效地管理堆内存。

  • -XX:MaxGCPauseMillis:设置垃圾收集器的最大停顿时间,推荐将该参数设置为 200 毫秒到 500 毫秒之间。例如,可以设置为 -XX:MaxGCPauseMillis=200,表示最大停顿时间为 200 毫秒。

  • -XX:+HeapDumpOnOutOfMemoryError:在发生内存溢出时生成堆转储文件。可以通过分析堆转储文件来找出内存泄漏等问题。

  • -XX:HeapDumpPath:指定堆转储文件的保存路径。

  • 示例 JVM 参数:

  • java -Xmx48g -Xms16g -Xmn16g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump/file -jar your_application.jar

  • 注意:JVM 参数的设置应根据具体情况进行调整。如果你的应用程序的内存占用较小,可以适当减少 -Xmx 和 -Xms 的设置;如果应用程序的性能存在问题,可以尝试调整垃圾收集器相关的参数。

jvm 优化篇-(8)-跨代引用问题(RememberSet、CardTable、ModUnionTable、DirtyCard)

红色的线表示由虚拟机栈中发出的引用。显然B---》A、E---》F都是跨代引用。

这里重点讲一下CardTable:
        作用:采用空间换时间,不需要扫描整个Heap空间,降低MonitorGC耗时。跨代引用带来的问题,采用CardTable很好的规避了遍历整个老年代的问题。
        HotSpot JVM的卡页(Card Page)大小为512字节,卡表(Card Table)被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。

如上图发现:B、C所在的Card Page在CardTable中被标记上了。

CMS-OldGC回收分为7个步骤:

【思考】CMS oldgc中remark耗时问题,跨代引用是图一中的B---》A 还是 E---》F?
答案:E---》F。
通过: -XX:+CMSScavengeBeforeRemark ,触发MonitorGC降低的就是YoungGen区的对象,从而达到标记源头减少,降低remark时间。
【思考】CMS 跨代引用是图一中的B---》A 有何危害,虚拟机是如何避开的?
答案:CardTable。
逻辑:采用创建CardTable空间区域,来避免扫整个老年代。当B无引用的时候,cardTable会被标记,一次MonitorGC就会回收掉。B是如何做到没引用的,同E---》F是一样的逻辑。

【思考】CMS里有两个需要STW的阶段:initial mark,remark、这两个标记有什么不一样么?使用的GC-Root一样么?
答案:不一样。
初始标记:使用的是常规的GC-Root(虚拟机栈栈帧中的局部变量表、本地方法栈native方法、方法区中类的静态属性和方法、方法区中常量等引用的对象)
重新标记:

【思考】同时带来了另外一个问题,MonitorGC可没有遍历整个老年代,而是采用CardTable通过时间换空间的做法,CMS-OldGC为什么采用遍历新生代所有的对象呢?
        这就是YoungGen 与 OldGen存在明显的差异:

【思考】既然initial mark阶段+concurrent mark阶段已经扫果了young gen 为何还要再次Remark?

【思考】CardTable与mod-union table有什么关系,都是干什么的?

华为三面:如何做JVM运行状态评估及优化

估算系统QPS,每个请求会创建多少对象,占多少内存,机器配置选型,年轻代应该给多少内存,YGC触发频率,对象进入老年代的速率,老年代应该给多少内存,Full GC触发的频率。这些都是根据代码可大概合理预估的。

预估完成后,就能采用优化思路,先给自己的系统设置一些初始JVM参数。如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值等。

优化思路很简单,尽量让:

每次 YGC 后的存活对象 Survivor区/2

保证都留存在年轻代里。尽量不让对象进入老年代,以减少Full GC频率,避免频繁Full GC影响JVM性能。

一个新系统开发完后,会经过本地的单元测试,到系统集成测试,再到测试环境的功能测试,预发布环境的压力测试,要保证系统的功能全部正常。在一定压力下性能、稳定性和并发能力都正常,最后才会部署到生产环境运行。

关键环节就是预发布环境的压力测试,会使用一些压力测试工具模拟比如1000个用户同时访问系统,造成每秒500个请求的压力,然后看系统能否支撑住每秒500请求的压力。同时看系统各个接口的响应延时是否在比如200ms内或在数据库中模拟出来百万级单表数据,然后看系统是否还能稳定运行。

具体如何进行系统压测,不是我们这里要讲述的内容,大家自行百度一下“Java压力测试”,就会看到很多开源的工具,可以轻松模拟出N个用户同时访问你系统的场景,还能给你一份压力测试报告,告诉你系统可以支撑每秒多少请求,包括系统接口的响应延时。通常压测工具会对系统发起持续不断的请求,持续很长时间,比如几个小时,甚至几天时间。

所以此时完全就可以在这个环节,对测试机器运行系统,采用jstat分析模拟真实环境的压力下,JVM运行状态。

然后根据压测环境JVM运行状况,如发现对象过快进入老年代,就需要采用之前介绍的优化思路,合理调整新生代、老年代、Eden、Survivor各个区域的内存大小,保证对象尽量留在年轻代,不要过快进入老年代。

当对压测环境下的系统优化好JVM参数之后,观察Young GC和Full GC频率都很低,此时就可部署上线。

每天高峰、低峰期用jstat、jmap、jhat等工具观察线上系统的JVM运行是否正常,有无频繁Full GC的问题。有就优化,没有就平时每天都定时或每周都看看。

如Zabbix、OpenFalcon、Ganglia,然后你部署的系统都可以把JVM统计项发送到这些监控系统里去。

此时你就可以在这些监控系统可视化的界面里,看到你需要的所有指标,包括你的各个内存区域的对象占用变化曲线,直接可以看到Eden区的对象增速,还会告诉你Young GC发生的频率以及耗时,包括老年代的对象增速以及Full GC的频率和耗时。

而且这些工具还允许你设置监控。即指定一个监控规则,比如线上系统的JVM,如果10分钟之内发生5 次以上Full GC,就需要发送报警给你。比如发送到你的邮箱、短信。

其实把这些命令行用好了,基本线上系统的JVM监控和优化都能搞定了。

线上运行系统,要不然用命令行工具手动监控,发现问题就优化,要不然就是依托公司监控系统,可视化查看日常系统的运行状态。

ElasticSearch性能优化实践(JVM调优+ES调优)

近一年内对公司的 ELK 日志系统做过性能优化,也对 SkyWalking 使用的 ES 存储进行过性能优化,在此做一些总结。本篇主要是讲 ES 在 ELK 架构中作为日志存储时的性能优化方案。

随着接入ELK的应用越来越多, 每日新增索引约 230 个,新增 document 约 3000万到 5000万

每日上午和下午是日志上传高峰期,在 Kibana 上查看日志,发现问题:
(1) 日志会有 5-40 分钟的延迟
(2) 有很多日志丢失,无法查到

数据先是存放在 ES 的内存 buffer,然后执行 refresh 操作写入到操作系统的内存缓存 os cache,此后数据就可以被搜索到。

所以,日志延迟可能是我们的数据积压在 buffer 中没有进入 os cache 。

查看日志发现很多 write 拒绝执行的情况

从日志中可以看出 ES 的 write 线程池已经满负荷,执行任务的线程已经达到最大16个线程,而200容量的队列也已经放不下新的task。

查看线程池的情况也可以看出 write 线程池有很多写入的任务

所以我们需要优化 ES 的 write 的性能。

ES 的优化分为很多方面,我们要根据使用场景考虑对 ES 的要求。

根据个人实践经验,列举三种不同场景下的特点

这三类场景的特点如下:

关于实时性

可以从三方面进行优化:JVM性能调优、ES性能调优、控制数据来源

可以从三方面进行优化:JVM 性能调优、ES 性能调优、控制数据来源

第一步是 JVM 调优。
因为 ES 是依赖于 JVM 运行,没有合理的设置 JVM 参数,将浪费资源,甚至导致 ES 很容易 OOM 而崩溃。

(1) 查看 GC 日志

(2) 使用 jstat 看下每秒的 GC 情况

用下面几种方式都可查看新、老年代内存大小
(1) 使用 jstat -gc pid 查看 Eden 区、老年代空间大小
(2) 使用 jmap -heap pid 查看 Eden 区、老年代空间大小
(3) 查看 GC 日志中的 GC 明细

上面的几种方式都查询出,新生代总内存约1081M,即1G左右;老年代总内存为19864000K,约19G。新、老比例约1:19,出乎意料。

这真是一个容易踩坑的地方。
如果没有显示设置新生代大小,JVM 在使用 CMS 收集器时会自动调参,新生代的大小在没有设置的情况下是通过计算得出的,其大小可能与 NewRatio 的默认配置没什么关系而与 ParallelGCThreads 的配置有一定的关系。

所以: 新生代大小有不确定性,最好配置 JVM 参数 -XX:NewSize、-XX:MaxNewSize 或者 -xmn ,免得遇到一些奇怪的 GC,让人措手不及。

新生代过小,老年代过大的影响

32G 的内存,分配 20G 给堆内存是不妥当的,所以调整为总内存的50%,即16G。
修改 elasticsearch 的 jvm.options 文件

设置要求:

因为指定新生代空间大小,导致 JVM 自动调参只分配了 1G 内存给新生代。

修改 elasticsearch 的 jvm.options 文件,加上

老年代则自动分配 16G-8G=8G 内存,新生代老年代的比例为 1:1。修改后每次 Young GC 频率更低,且每次 GC 后只有少数数据会进入老年代。

ES默认使用的垃圾回收器是:老年代(CMS)+ 新生代(ParNew)。如果是JDK1.9,ES 默认使用G1垃圾回收器。

因为使用的是 JDK1.8,所以并未切换垃圾回收器。后续如果再有性能问题再切换G1垃圾回收器,测试是否有更好的性能。

优化前

每秒打印一次 GC 数据。可以看出,年轻代增长速度很快,几秒钟年轻代就满了,导致 Young GC 触发很频繁,几秒钟就会触发一次。而每次 Young GC 很大可能有存活对象进入老年代,而且,存活对象多的时候(看上图中第一个红框中的old gc数据),有(51.44-51.08)/100 * 19000M = 约68M。每次进入老年代的对象较多,加上频繁的 Young GC,会导致新老年代的分代模式失去了作用,相当于老年代取代了新生代来存放近期内生成的对象。当老年代满了,触发 Full GC,存活的对象也会很多,因为这些对象很可能还是近期加入的,还存活着,所以一次 Full GC 回收对象不多。而这会恶性循环,老年代很快又满了,又 Full GC,又残留一大部分存活的,又很容易满了,所以导致一直频繁 Full GC。

优化后

每秒打印一次 GC 数据。可以看出,新生代增长速度慢了许多,至少要60秒才会满,如上图红框中数据,进入老年代的对象约(15.68-15.60)/100 * 10000 = 8M,非常的少。所以要很久才会触发一次 Full GC 。而且等到 Full GC 时,老年代里很多对象都是存活了很久的,一般都是不会被引用,所以很大一部分会被回收掉,留一个比较干净的老年代空间,可以继续放很多对象。

ES 启动后,运行14个小时

优化前

Young GC 每次的时间是不长的,从上面监控数据中可以看出每次GC时长 1467.995/27276 约等于 0.05秒。那一秒钟有多少时间实在处理Young GC ? 计算公式:1467秒/ (60秒×60分 14小时)= 约0.028秒,也就是100秒中就有2.8秒在Young GC,也就是有2.8S的停顿,这对性能还是有很大消耗的。同时也可以算出多久一次Young GC, 方程是: 60秒×60分*14小时/ 27276次 = 1次/X秒,计算得出X = 0.54,也就是0.54秒就会有一次Young GC,可见 Young GC 频率非常频繁。

优化后

Young GC 次数只有修改前的十分之一,Young GC 时间也是约八分之一。Full GC 的次数也是只有原来的八分之一,GC 时间大约是四分之一。

GC 对系统的影响大大降低,性能已经得到很大的提升。

上面已经分析过ES作为日志存储时的特性是:高并发写、读少、接受30秒内的延时、可容忍部分日志数据丢失。
下面我们针对这些特性对ES进行调优。

本人整理了一下数据写入的底层原理

refresh
ES 接收数据请求时先存入 ES 的内存中,默认每隔一秒会从内存 buffer 中将数据写入操作系统缓存 os cache,这个过程叫做 refresh;

到了 os cache 数据就能被搜索到(所以我们才说 ES 是近实时的,因为1s 的延迟后执行 refresh 便可让数据被搜索到)

fsync
translog 会每隔5秒或者在一个变更请求完成之后执行一次 fsync 操作,将 translog 从缓存刷入磁盘,这个操作比较耗时,如果对数据一致性要求不是跟高时建议将索引改为异步,如果节点宕机时会有5秒数据丢失;

flush
ES 默认每隔30分钟会将 os cache 中的数据刷入磁盘同时清空 translog 日志文件,这个过程叫做 flush。

merge

ES 的一个 index 由多个 shard 组成,而一个 shard 其实就是一个 Lucene 的 index ,它又由多个 segment 组成,且 Lucene 会不断地把一些小的 segment 合并成一个大的 segment ,这个过程被称为 段merge 。执行索引操作时, ES会先生成小的segment ,ES 有离线的逻辑对小的 segment 进行合并,优化查询性能。但是合并过程中会消耗较多磁盘 IO,会影响查询性能。

为了保证不丢失数据,就要保护 translog 文件的安全:

该方式提高数据安全性的同时, 降低了一点性能.

==》 频繁地执行 fsync 操作, 可能会产生阻塞导致部分操作耗时较久. 如果允许部分数据丢失, 可设置异步刷新 translog 来提高效率,还有降低 flush 的阀值,优化如下:

写入 Lucene 的数据,并不是实时可搜索的,ES 必须通过 refresh 的过程把内存中的数据转换成 Lucene 的完整 segment 后,才可以被搜索。

默认1秒后,写入的数据可以很快被查询到,但势必会产生大量的 segment,检索性能会受到影响。所以,加大时长可以降低系统开销。对于日志搜索来说,实时性要求不是那么高,设置为5秒或者10s;对于SkyWalking,实时性要求更低一些,我们可以设置为30s。

设置如下:

index.merge.scheduler.max_thread_count 控制并发的 merge 线程数,如果存储是并发性能较好的 SSD,可以用系统默认的 max(1, min(4, availableProcessors / 2)),当节点配置的 cpu 核数较高时,merge 占用的资源可能会偏高,影响集群的性能,普通磁盘的话设为1,发生磁盘 IO 堵塞。设置max_thread_count 后,会有 max_thread_count + 2 个线程同时进行磁盘操作,也就是设置为 1 允许3个线程。

设置如下:

该方式可对已经生成的索引做修改,但是对于后续新建的索引不生效,所以我们可以制作 ES 模板,新建的索引按模板创建索引。

因为我们的业务日志是按天维度创建索引,索引名称示例:user-service-prod-2020.12.12,所以用通配符 202 ..*匹配对应要创建的业务日志索引。

前文已经提到过,write 线程池满负荷,导致拒绝任务,而有的数据无法写入。

而经过上面的优化后,拒绝的情况少了很多,但是还是有拒绝任务的情况。

所以我们还需要优化write线程池。

从 prometheus 监控中可以看到线程池的情况:

为了更直观看到ES线程池的运行情况,我们安装了 elasticsearch_exporter 收集 ES 的指标数据到 prometheus,再通过 grafana 进行查看。

经过上面的各种优化,拒绝的数据量少了很多,但是还是存在拒绝的情况,如下图:

write 线程池如何设置:

参考: ElasticSearch线程池

write 线程池采用 fixed 类型的线程池,也就是核心线程数与最大线程数值相同。线程数默认等于 cpu 核数,可设置的最大值只能是 cpu 核数加1,也就是16核CPU,能设置的线程数最大值为17。

优化的方案:

config/elasticsearch.yml文件增加配置

优化后效果

Swap 交换分区 :

参考: ElasticSearch官方解释为什么要禁用交换内存

有三种方式可以实现 ES 不使用Swap分区

执行命令

可以临时禁用 Swap 内存,但是操作系统重启后失效

执行下列命令

正常情况下不会使用 Swap,除非紧急情况下才会 Swap。

config/elasticsearch.yml 文件增加配置

分片

索引的大小取决于分片与段的大小,分片过小,可能导致段过小,进而导致开销增加;分片过大可能导致分片频繁 Merge,产生大量 IO 操作,影响写入性能。

因为我们每个索引的大小在15G以下,而默认是5个分片,没有必要这么多,所以调整为3个。

分片的设置我们也可以配置在索引模板。

副本数

减少集群副本分片数,过多副本会导致 ES 内部写扩大。副本数默认为1,如果某索引所在的1个节点宕机,拥有副本的另一台机器拥有索引备份数据,可以让索引数据正常使用。但是数据写入副本会影响写入性能。对于日志数据,有1个副本即可。对于大数据量的索引,可以设置副本数为0,减少对性能的影响。

分片的设置我们也可以配置在索引模板。

有的应用1天生成10G日志,而一般的应用只有几百到1G。一天生成10G日志一般是因为部分应用日志使用不当,很多大数量的日志可以不打,比如大数据量的列表查询接口、报表数据、debug 级别日志等数据是不用上传到日志服务器,这些 即影响日志存储的性能,更影响应用自身性能

优化后的两周内ELK性能良好,没有使用上的问题:

参考

JVM对于声明为final的局部变量做了哪些性能优化

在能够通过编译的前提下,无论局部变量声明时带不带final关键字修饰,对其访问的效率都一样。原问题里引用的Android代码的“优化”与“final”没关系,只与“局部变量”有关——重复访问一个局部变量比重复访问一个成员或静态变量快;即便将其final修饰符去掉,效果也一样。

关于jvm优化和64g内存服务器+jvm参数的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

64g内存服务器+jvm参数?jvm 优化篇-(8)-跨代引用问题(RememberSet、CardTable、ModUnionTable、DirtyCard)

本文编辑:admin

更多文章:


springmvc的依赖(springMVC的注入方式有哪几种,这与springMVC依赖)

springmvc的依赖(springMVC的注入方式有哪几种,这与springMVC依赖)

大家好,关于springmvc的依赖很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于springMVC的注入方式有哪几种,这与springMVC依赖的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还

2026年9月7日 14:00

it培训评价网(it培训排名机构十大IT培训机构)

it培训评价网(it培训排名机构十大IT培训机构)

这篇文章给大家聊聊关于it培训评价网,以及it培训排名机构十大IT培训机构对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

2026年9月7日 13:00

个人博客页面布局(新手站长怎样做好独立博客初期运营工作)

个人博客页面布局(新手站长怎样做好独立博客初期运营工作)

大家好,如果您还对个人博客页面布局不太了解,没有关系,今天就由本站为大家分享个人博客页面布局的知识,包括新手站长怎样做好独立博客初期运营工作的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

2026年9月7日 12:40

display flex 自动换行(overflow-y:hidden;overflow-x:auto;无效解决方法)

display flex 自动换行(overflow-y:hidden;overflow-x:auto;无效解决方法)

大家好,关于display flex 自动换行很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于overflow-y:hidden;overflow-x:auto;无效解决方法的知识点,相信应该可以解决大家的一些困惑和问题,如

2026年9月7日 11:00

小程序免认证源码(小程序源码都能干嘛)

小程序免认证源码(小程序源码都能干嘛)

本篇文章给大家谈谈小程序免认证源码,以及小程序源码都能干嘛对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

2026年9月7日 10:50

timestamp without time zone(Postgresql中to_date()函数使用问题)

timestamp without time zone(Postgresql中to_date()函数使用问题)

各位老铁们好,相信很多人对timestamp without time zone都不是特别的了解,因此呢,今天就来为大家分享下关于timestamp without time zone以及Postgresql中to_date()函数使用问题

2026年9月7日 09:40

网页制作代码特效大全(谁知道网页打字机特效的代码)

网页制作代码特效大全(谁知道网页打字机特效的代码)

大家好,如果您还对网页制作代码特效大全不太了解,没有关系,今天就由本站为大家分享网页制作代码特效大全的知识,包括谁知道网页打字机特效的代码的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

2026年9月7日 04:20

下载mysql的步骤(win10安装mysql的步骤和方法)

下载mysql的步骤(win10安装mysql的步骤和方法)

各位老铁们,大家好,今天由我来为大家分享下载mysql的步骤,以及win10安装mysql的步骤和方法的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

2026年9月7日 04:10

webstorm怎么读(webstorm文件结构怎么打开)

webstorm怎么读(webstorm文件结构怎么打开)

本篇文章给大家谈谈webstorm怎么读,以及webstorm文件结构怎么打开对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

2026年9月7日 03:50

nio新特性(Java NIO与IO的区别和比较)

nio新特性(Java NIO与IO的区别和比较)

各位老铁们好,相信很多人对nio新特性都不是特别的了解,因此呢,今天就来为大家分享下关于nio新特性以及Java NIO与IO的区别和比较的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

2026年9月7日 03:40

最近更新

热门文章

yoga pro 14s carbon(yoga14s接口类型)
2026-07-03 17:50:01 浏览:5
domino directory(帮我翻译一下Recipient’s Domino Directory entry does not specify a valid Notes mail file)
2026-08-03 19:20:01 浏览:4
标签列表