当前位置:  开发笔记 > 编程语言 > 正文

针对大型应用程序的JVM性能调优

如何解决《针对大型应用程序的JVM性能调优》经验,为你挑选了3个好方法。

默认JVM参数不是运行大型应用程序的最佳选择.来自在真实应用程序上进行调整的人的任何见解都会有所帮助.我们在32位Windows机器上运行应用程序,默认情况下使用客户机JVM .我们添加了-server并将NewRatio更改为1:3(更大的年轻一代).

您尝试过并发现有用的任何其他参数/​​调整?

[更新]我正在谈论的特定类型的应用程序是一个很少关闭的服务器应用程序,至少需要-Xmx1024m.还假设已经分析了应用程序.我正在寻找仅在JVM性能方面的一般准则.



1> user5994461..:
前言

背景

去过Java商店.花了整整几个月专门在分布式系统上运行性能测试,主要应用程序是Java.其中一些暗示Sun自己(然后是Oracle)开发和销售的产品.

我将介绍我学到的经验教训,一些关于JVM的历史,一些关于内部的讨论,一些参数的解释以及最后的一些调整.试着保持这一点,以便你可以在实践中应用它.

Java世界的情况正在快速变化,因此自去年我完成所有这些工作以来,其中一部分可能已经过时了.(Java 10已经出来了吗?)

好的做法

你应该做什么:基准,Benchmark,BENCHMARK!

当您真正需要了解性能时,您需要针对您的工作负载执行真正的基准测试.没有其他选择.

此外,您应该监视JVM.启用监控.好的应用程序通常提供监视网页和/或API.否则就有常见的Java工具(JVisualVM,JMX,hprof和一些JVM标志).

请注意,通过调整JVM通常无法获得性能.它更像是"崩溃或不崩溃,找到过渡点".这是关于知道,当你给资源量到您的应用程序,你可以持续期待的是回报的演出量.知识就是力量.

表演主要取决于您的申请.如果你想要更快,你必须编写更好的代码.

大多数时候你会做什么:生活在可靠的敏感默认值下

我们没有时间优化和调整每个应用程序.大多数时候,我们只会使用合理的默认值.

配置新应用程序时要做的第一件事是阅读文档.大多数严肃的应用程序都附带了性能调优指南,包括有关JVM设置的建议.

然后您可以配置应用程序: JAVA_OPTS: -server -Xms???g -Xmx???g

-server:启用完全优化(此标志现在在大多数JVM上是自动的)

-Xms -Xmx:设置最小和最大堆(两者总是相同的值,这是唯一要做的优化).

干得好,你知道有关JVM的所有优化参数,恭喜!这很简单:D

你不应该做的,永远:

请不要复制您在互联网上找到的随机字符串,特别是当它们采用多行时:

-server  -Xms1g -Xmx1g  -XX:PermSize=1g -XX:MaxPermSize=256m  -Xmn256m -Xss64k  -XX:SurvivorRatio=30  -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled  -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=10  -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark  -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Dsun.net.inetaddr.ttl=5  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=`date`.hprof   -Dcom.sun.management.jmxremote.port=5616 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC

例如,谷歌第一页上发现的这件事很明显.有些参数指定了具有冲突值的倍数.有些只是强制JVM默认值(最终默认来自2个JVM版本).有些是过时的,完全被忽略了.最后,至少有一个参数是如此无效,以至于它会在启动时始终使JVM崩溃,因为它只是存在.

实际调整

你如何选择内存大小:

从您的应用程序阅读指南,它应该给出一些指示.监控生产并随后进行调整.如果您需要准确性,请执行一些基准测试

重要说明:java进程最多需要10%的最大堆.X%开销是堆管理,不包含在堆本身中.

所有内存通常由启动时的进程预先分配.您可以使用max heap ALL THE TIME查看进程.这根本不是真的.您需要使用Java监视工具来查看实际使用的内容.

找到合适的尺寸:

如果它与OutOfMemoryException崩溃,则内存不足

如果它没有与OutOfMemoryException崩溃,那就是内存太多了

如果它的内存太多,但硬件得到它和/或已经付费,那就是完美的数字,完成工作!

JVM6是青铜器,JVM7是金牌,JVM8是铂金......

JVM永远在改进.垃圾收集是一件非常复杂的事情,有很多非常聪明的人在研究它.它在过去十年中取得了巨大的进步,并将继续这样做.

用于提供信息.它们是Oracle Java 7-8(HotSpot)和OpenJDK 7-8中至少4个可用的垃圾收集器.(其他JVM可能完全不同,例如Android,IBM,嵌入式):

SerialGC

ParallelGC

ConcurrentMarkSweepGC

G1GC

(加上变种和设置)

[从Java 7开始,继续.Oracle和OpenJDK代码是部分共享的.GC(在大多数情况下)应该在两个平台上都相同.

JVM> = 7有很多优化并且选择了不错的默认值.它按平台改变了一点.它平衡了许多事情.例如,决定是否启用多核优化,而不是CPU是否具有多个核心.你应该让它做到.请勿更改或强制GC设置.

让计算机为你决定(这就是计算机的用途)是可以的.最好让JVM设置始终保持95%的最佳状态,而不是在所有方框上强制"总是8核心积极收集以减少暂停时间",其中一半最终为t2.small.

例外:当应用程序附带性能指南和特定调整时.保留所提供的设置是完全可以的.

提示:迁移到较新的JVM以从最新的改进中受益有时可以毫不费力地提供良好的提升.

特例:-XX:+ UseCompressedOops

JVM有一个特殊的设置,强制在内部使用32位索引(读取:指针式).这允许寻址4 294 967 295个对象*8个字节地址=> 32 GB的内存.(不要与REAL指针的4GB地址空间混淆).

它可以降低整体内存消耗,并对所有缓存级别产生潜在的积极影响.

现实生活中的例子:ElasticSearch文档指出,就内存中保存的实际数据而言,运行的32GB 32位节点可能相当于40GB的64位节点.

关于历史的一个注释:在java-7之前的时代(甚至可能是java-6之前的版本),已知该旗帜是不稳定的.它已经在新的JVM中运行了一段时间.

Java HotSpot™虚拟机性能增强

[...]在Java SE 7中,当未指定-Xmx且-Xmx值小于32千兆字节时,使用压缩oops是64位JVM进程的缺省值.对于6u23发行版之前的JDK 6,请使用-XX:+ UseCompressedOops标志和java命令来启用该功能.

请参阅:JVM在手动调整方面再次亮相.知道它仍然很有趣=)

特例:-XX:+ UseNUMA

非均匀存储器访问(NUMA)是用于多处理的计算机存储器设计,存储器访问时间取决于相对于处理器的存储器位置.资料来源:维基百科

现代系统具有极其复杂的内存架构,在内核和CPU上具有多层内存和高速缓存(私有和共享).

很明显,在当前处理器中访问L2缓存中的数据比从另一个套接字一直到记忆棒要快得多.

我相信今天销售的所有多插槽系统都是NUMA设计,而所有消费者系统都不是.使用numactl --showlinux 上的命令检查您的服务器是否支持NUMA .

NUMA-aware标志告诉JVM优化底层硬件拓扑的内存分配.

性能提升可能很大(即两位数:+ XX%).实际上有人从"NOT-NUMA 10CPU 100GB"切换到"NUMA 40CPU 400GB",如果他不了解旗帜,可能会遇到[戏剧性]性能损失.

注意:有讨论要检测NUMA并在JVM中自动设置标志http://openjdk.java.net/jeps/163

额外奖励:所有打算在大型硬件硬件(即NUMA)上运行的应用程序都需要针对它进行优化.它不是特定于Java应用程序.

走向未来:-XX:+ UseG1GC

垃圾收集的最新改进是G1收集器(读取:Garbage First).

它适用于高内核,高内存系统.绝对最少4核+ 6 GB内存.它使用10次以上的数据库和内存密集型应用程序.

简短版本,在这些尺寸下,传统的GC面临着过多的数据需要立即处理,而暂停则失控.G1在许多小部分中拆分堆,这些部分可以在应用程序运行时独立并行地进行管理.

第一个版本于2013年推出.它已经足够成熟,现在可以生产,但不会很快就会出现默认情况.这对于大型应用程序来说值得一试.

请勿触摸:生成大小(NewGen,PermGen ......)

GC将内存分成多个部分.(没有详细说明,你可以google"Java GC Generations".)

我最近一次花了一个星期的时间尝试20个不同的代组合标志在一个应用程序上获得10000点击/秒.我获得了-1%到+ 1%的惊人提升.

Java GC代是一个有趣的主题,可以阅读论文或撰写论文.它们不是一个可以调整的东西,除非你是1%的人中的一员,他们可以在1%真正需要优化的人中投入大量时间获得微不足道的收益.

结论

希望这可以帮到你.享受JVM的乐趣.

Java是世界上最好的语言和最好的平台!去传播爱情:D



2> Charlie Mart..:

周围有大量的信息.

首先,在调优JVM之前分析代码.

其次,仔细阅读JVM文档 ; 周围有很多"城市传说".例如,-server标志仅在JVM保持驻留并运行一段时间时才有用; -server"关闭"JIT/HotSpot,并且需要通过相同的路径进行多次传递才能启动.另一方面,-server 减慢了JVM的初始执行速度,因为设置时间更长.

周围有好几本好书和网站.例如,请参阅http://www.javaperformancetuning.com/



3> TofuBeer..:

看这里(或谷歌搜索热点调整)http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

在尝试调整虚拟机之前,您肯定想要分析您的应用.NetBeans内置了一个很好的分析器,可以让你看到各种各样的东西.

我曾经有人告诉我,他们的应用程序中断了GC - 我查看了代码并发现他们从未关闭任何数据库查询结果,因此他们保留了大量的字节数组.一旦我们关闭结果,时间从超过20分钟和GB内存到大约2分钟和非常少量的内存.他们能够删除JVM调整参数,事情很愉快.

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有