JVMの高速チューンLiuyouマニュアル:JVMパラメータの設定と分析

かどうかYGCのフルGC、GCプロセスは、実行するためのプログラムが中断された原因となるさまざまなGCポリシーの正しい選択、パラメータのJVMを調整し、GC、およびランニングを大幅に割り込み側面につながったGCの仕事を、減らすことができます問題は、その後、Javaプログラムの効率を向上させる適切な。各プログラムのような異なる特性、持っているのでしかし、GCは非常に複雑なプロセスで調整します。Web GUIプログラムをと大きな差がある(ウェブは、適切な一時停止することができますが、一時停止のGUIクライアントは許容されない)により実行することが、また、各マシン上の異なる構成(異なるメモリの主カップ数)ので、GCは、使用の異なる種類(方法を選択し、どのようにGCの種類を選択する参照)であろう。この記事では、システムのパフォーマンスを向上させるために、GCのいくつかの重要なパラメータを設定し、導入JVMに焦点を当てます。

GC&メモリ割り当て戦略で構成JVMのメモリ:以前の記事JVMのメモリコンポーネントおよびGCのコンテンツを参照してください。

JVMパラメータ意味

ケーススタディの例を参照してください。

パラメータ 名前 意味 デフォルト値
-Xms 初期ヒープサイズ 物理メモリ1/64(<1ギガバイト) デフォルト(MinHeapFreeRatioパラメータが調整されてもよい)スペアヒープメモリが40%未満であり、JVMスタックは-Xmxの上限まで増加するであろう。
-Xmx 最大ヒープサイズ 物理メモリの1/4(<1ギガバイト フリーメモリヒープのデフォルトは、(パラメータがMaxHeapFreeRatioを調整することができる)70%以上であり、JVMは-Xmsまでスタックの下限値を減少させます
-Xmn 若い世代のサイズ 1.4or lator 注:ここでのサイズは(エデン+ 2 Survivor領域)で、新世代-heap jmapの表示異なっています。

ヒープサイズ=サイズ+永続的な世代のサイズの大きさ+旧世代を通じて若い世代。

若い世代の増加した後、旧世代のサイズを小さくします。システムのパフォーマンスにこの値より大きなインパクトを、Sunの関係者は、ヒープ全体の構成をお勧めします3/8

-XX:NewSizeパラメータ|(1.3 / 1.4用)若い世代のサイズを設定します|

-XX:MaxNewSize |(1.3 / 1.4用)の最大値の若い世代|

-XX:PermSizeを|に配置された永久世代(パーマ世代)初期値|物理メモリ1/64

-XX:MaxPermSizeを|物理メモリの1/4 |最大Permanent世代を設定します

-Xss |各スレッドのスタックサイズ後の各スレッド|| JDK5.0のスタックサイズは、各スレッドのスタックサイズは256Kアプリケーションメモリサイズの複数のスレッドが同じ物理メモリ内に調整される必要とされる前に、1Mです、。この値を小さくすると、より多くのスレッドを生成し、そのプロセス内のオペレーティング・システムのスレッドの数はまだ3000と5000には、いない無制限の世代、経験を制限することができます。

一般的に、小さなアプリケーションスタックが非常に深いではない場合、それは、使用アプリケーションの推奨128Kの256Kのために十分な大きさでなければなりません。このオプションは、パフォーマンスに比較的大きな影響が厳格なテストが必要です。(プリンシパル)とTHREADSTACKSIZEオプションは、フォーラムでこのような言葉があり、公式の文書は何の説明もないようだと非常によく似て説明されている:「 - XSSはThreadStackSizeは名前のVMフラグに翻訳され、」一般的にその上に、この値を設定します。

-XX:ThreadStackSizeは|スレッドスタックサイズ||(0手段は、デフォルトのスタック・サイズを使用)[SPARC:512; Solarisのx86:320(前5.0およびそれ以前では256でした)。SPARC 64ビット:1024; Linux AMD64:1024(5.0およびそれ以前では0でした)。他のすべて0]

-XX:NewRatio |(エデンと2つのサバイバー領域を含む)若い世代と(永久世代を除く)、旧世代の比率|| -XX:、4:NewRatio = 4は、若い世代を表し、古い世代が1の比率を占めていましたスタック全体の1/5のために若い世代アカウント

パラメータの設定は必要ないXMS = XmxのケースとXMNセット。

-XX:|:合計のサバイバー若い世代領域1/10、8 SurvivorRatioエデン領域とサイズ比領域||サバイバーは8に設定され、サバイバーエデンゾーンを有する2つの領域の比は2

-XX:LargePageSizeInBytes |メモリ・ページ・サイズが大きすぎる設定することはできませんが、パーマ|| = 128メートルの大きさに影響を与えます

-XX:+ UseFastAccessorMethods |の元の型の迅速な最適化

-XX:+ DisableExplicitGC |閉じるにSystem.gc()||このパラメータは、厳密なテストが必要です

-XX:.. MaxTenuringThreshold |ごみ最大の年齢|| 0に設定した場合、この値に設定されている場合、その後、より多くのアプリケーションの古い世代へのサバイバー領域なしで、直接、古い世代にオブジェクトの若い世代は、効率を向上させることができますより高い値は、若い世代のオブジェクトは、オブジェクトを増加させ、その後、生存期間の若い世代は、若い世代のIEの回復の確率を高めることができ、サバイバー領域に何回もコピーされます

このパラメータは、ときにのみ、シリアルGC効果的です。

-XX:+ AggressiveOpts |コンパイルをスピードアップ

-XX:+ UseBiasedLocking |パフォーマンスはロック機構を改善

-Xnoclassgc |無効にガベージコレクション

-XX:SoftRefLRUPolicyMSPerMB |每兆堆空闲空间中SoftReference的存活时间| 1S |そっと到達可能なオブジェクトは、彼らが参照された最後の時間後の時間のいくつかの量のために生きているままになります。デフォルト値は、ヒープ内の空きメガバイトあたり生涯の1秒です

パラレル清掃をGCの新世代を使用して無効なバイト単位|旧世代内のオブジェクトを直接割り当てられているよりもはるかに| |をPretenureSizeThreshold 0:-XX

オブジェクトの大きな配列の直接的な分布の場合には別の旧世代、およびアレイ内の外部参照オブジェクト。

-XX:TLABWasteTargetPercent |エデン地域のTLAB率| 1%

-XX:+ CollectGen0First |偽| YGC FullGC初めてかどうか

パラレルコレクタパラメータ

パラメーター名 意味 デフォルト値
-XX:+ UseParallelGC パラレルMSCを使用してフルGC(これは認証されます) ガベージコレクタの並列コレクタを選択します。この構成では、若い世代のために効果的である。まだシリアルコレクターの古い世代を使用しながら、上記の構成、若い世代の同時収集、こと。(これが認証されます)
-XX:+ UseParNewGC 若いセットに代わって収集するために、パラレル CMSは、JVMは、システム構成に応じて、独自に設定することができ、上記の使用JDK5.0を収集することがあり、それはこの値を設定する必要はありません
-XX:ParallelGCThreads パラレルコレクタ内のスレッドの数 この値は、好ましくは、CMSにも同様に適用可能に配置されているプロセッサの数に等しいです。
-XX:+ UseParallelOldGC 並列コレクションの古い世代のガベージコレクション(パラレルコンパク) これは、パラメータオプションは、Java 6を表示されています
-XX:MaxGCPauseMillis たびに、若い世代のガベージコレクションは、最大時間(最大休止時間)であります あなたはこの時間を満たすことができない場合は、JVMが自動的にこの値を満たすために若い世代のサイズを調整します。

-XX:+ UseAdaptiveSizePolicyは自動的に、若い世代領域のサイズと対応するレートサバイバー領域を選択し
、このオプションが設定され、パラレルコレクタは自動的にターゲット・システムに対応する時間を所定の最小値を達成する、または収集するために、若い世代領域のサイズと対応するレートサバイバー領域を選択します周波数、パラレルコレクタは、開かれているとき、この値が推奨されます。
-XX:。GCTimeRatio | ||プログラムには時間が実行された時間の割合を表すガベージコレクションの式1 /(N + 1)
-XX:+ ScavengeBeforeFullGC |前のフルGC呼び出しYGC |真|若い世代のGCいますフルGC前に(1.4.1で導入を。)。

CMSパラメータ

パラメーター名 意味 デフォルト値
-XX:+ UseConcMarkSweepGCを CMSのガベージコレクションを使用します この試験の設定後に、-XX:NewRatio = 4の構成は、したがって、この時点で、若い世代のサイズは、好ましくは、-Xmnが設けられており、未知の理由のために、失敗しました?..
-XX:+ AggressiveHeap (メモリ、プロセッサの数)長い時間のために、大規模なメモリ使用量の最適化を物理メモリを大量に使用しようとしている、とコンピューティングリソースを確認することができ、あなたはすでにマシン上の1.4.1に(、最低でも256MBのメモリ、CPU /メモリの大容量を必要とする4CPU示したアップグレード)
-XX:CMSFullGCsBeforeCompaction 何回圧縮されたメモリ メモリ空間の同時収集整理、圧縮しないので、作業効率を低下させるように、それは、操作の期間後の「破片」を持つことになります。この値は、仕上げ、圧縮後に何回GCメモリ空間を実行するように設定されています。
-XX:+ CMSParallelRemarkEnabled 下停止マーク
-XX + UseCMSCompactAtFullCollection FULL GCでたときに古い世代の圧縮 CMSは、取り外し可能なメモリではありませんので、これは破片を生成することは非常に容易である、メモリ内の結果は、したがって、この時間圧縮のメモリが有効になり、十分ではありません。このパラメータを増やすことは良い習慣です。パフォーマンスが影響を受ける可能性がありますが、破片を除去することができます
-XX:+ UseCMSInitiatingOccupancyOnly 手動で使用するCMSの初期定義は、収集を開始した定義 hostspot自身のトリガーCMS GCを禁止
-XX:CMSInitiatingOccupancyFraction = 70 ガベージコレクションとしてCMSを使用して、CMSは70%を使用した後に集め始めました 92 プロモーションがあることを確実にするために、(下記参照)、エラーに失敗し、次の式満たすために必要な値に設定CMSInitiatingOccupancyFractionの式を
-XX:CMSInitiatingPermOccupancyFraction パーマジェンセットトリガ数は、使用率に達しました 92
-XX:+ CMSIncrementalMode インクリメンタルモードに設定してください 単一CPUの場合について
-XX:+ CMSClassUnloadingEnabled

補足情報

パラメーター名 意味 デフォルト値
-XX:+ PrintGC 出力フォーマット:[GC 118250K-> 113543K(130112K)、0.0094143秒] [完全GC 121376K-> 10414K(130112K)、0.0650971秒]
-XX:+ PrintGCDetails 输出形式: [GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs][GC [DefNew: 8614K->8614K(9088K), 0.0000665 secs][Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs]
-XX:+PrintGCTimeStamps
-XX:+PrintGC:PrintGCTimeStamps 可与-XX:+PrintGC -XX:+PrintGCDetails混合使用 输出形式:11.851: [GC 98328K->93620K(130112K), 0.0082960 secs]
-XX:+PrintGCApplicationStoppedTime 打印垃圾回收期间程序暂停的时间.可与上面混合使用 输出形式:Total time for which application threads were stopped: 0.0468229 seconds
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中断的执行时间.可与上面混合使用 输出形式:Application time: 0.5291524 seconds
-XX:+PrintHeapAtGC 打印GC前后的详细堆栈信息
-Xloggc:filename 把相关日志信息记录到文件以便分析. 与上面几个配合使用
-XX:+PrintClassHistogram garbage collects before printing the histogram.
-XX:+PrintTLAB 查看TLAB空间的使用情况
XX:+PrintTenuringDistribution 查看每次minor GC后新的存活周期的阈值 Desired survivor size 1048576 bytes, new threshold 7 (max 15)

new threshold 7即标识新的存活周期的阈值为7。

GC性能方面的考虑

对于GC的性能主要有2个方面的指标:吞吐量throughput(工作时间不算gc的时间占总的时间比)和暂停pause(gc发生时app对外显示的无法响应)

  1. Total Heap

    默认情况下,vm会增加/减少heap大小以维持free space在整个vm中占的比例,这个比例由MinHeapFreeRatio和MaxHeapFreeRatio指定。
    一般而言,server端的app会有以下规则:

    • 对vm分配尽可能多的memory;
    • 将Xms和Xmx设为一样的值。如果虚拟机启动时设置使用的内存比较小,这个时候又需要初始化很多对象,虚拟机就必须重复地增加内存。
    • 处理器核数增加,内存也跟着增大。
  2. The Young Generation

    另外一个对于app流畅性运行影响的因素是young generation的大小。young generation越大,minor collection越少;但是在固定heap size情况下,更大的young generation就意味着小的tenured generation,就意味着更多的major collection(major collection会引发minor collection)。
    NewRatio反映的是young和tenured generation的大小比例。NewSize和MaxNewSize反映的是young generation大小的下限和上限,将这两个值设为一样就固定了young generation的大小(同Xms和Xmx设为一样)。
    如果希望,SurvivorRatio也可以优化survivor的大小,不过这对于性能的影响不是很大。SurvivorRatio是eden和survior大小比例。
    一般而言,server端的app会有以下规则:

    • 首先决定能分配给vm的最大的heap size,然后设定最佳的young generation的大小;
    • 如果heap size固定后,增加young generation的大小意味着减小tenured generation大小。让tenured generation在任何时候够大,能够容纳所有live的data(留10%-20%的空余)。

经验&&规则

  • 年轻代大小选择

    • 响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.
    • 吞吐量优先的应用:尽可能的设置大,可能到达Gbit的程度.因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用.
    • 避免设置过小.当新生代设置过小时会导致:1.YGC次数更加频繁 2.可能导致YGC对象直接进入旧生代,如果此时旧生代满了,会触发FGC.
  • 年老代大小选择

    • 响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎 片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:
      并发垃圾收集信息、持久代并发收集次数、传统GC信息、花在年轻代和年老代回收上的时间比例。
    • 吞吐量优先的应用:一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代.原因是,这样可以尽可能回收掉大部分短期对象,减少中期的对象,而年老代尽存放长期存活对象.
  • 较小堆引起的碎片问题

    因为年老代的并发收集器使用标记,清除算法,所以不会对堆进行压缩.当收集器回收时,他会把相邻的空间进行合并,这样可以分配给较大的对象.但是,当堆空间较小时,运行一段时间以后,就会出现”碎片”,如果并发收集器找不到足够的空间,那么并发收集器将会停止,然后使用传统的标记,清除方式进行回收.如果出现”碎片”,可能需要进行如下配置:
    -XX:+UseCMSCompactAtFullCollection:使用并发收集器时,开启对年老代的压缩.
    -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩

  • 用64位操作系统,Linux下64位的jdk比32位jdk要慢一些,但是吃得内存更多,吞吐量更大

  • XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这样可以减轻伸缩堆大小带来的压力

  • 使用CMS的好处是用尽量少的新生代,经验值是128M-256M, 然后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间非常的短,2G的内存, 大约20-80ms的应用程序停顿时间

  • 系统停顿的时候可能是GC的问题也可能是程序的问题,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多问题。(相关工具的使用方法将在后面的blog中介绍)

  • 仔细了解自己的应用,如果用了缓存,那么年老代应该大一些,缓存的HashMap不应该无限制长,建议采用LRU算法的Map做缓存,LRUMap的最大长度也要根据实际情况设定。

  • 采用并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿

  • JVM参数的设置(特别是 –Xmx –Xms –Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold等参数的设置没有一个固定的公式,需要根据PV old区实际数据 YGC次数等多方面来衡量。为了避免promotion faild可能会导致xmn设置偏小,也意味着YGC的次数会增多,处理并发访问的能力下降等问题。每个参数的调整都需要经过详细的性能测试,才能找到特定应用的最佳配置。

promotion failed

垃圾回收时promotion failed是个很头痛的问题,一般可能是两种原因产生,第一个原因是救助空间不够,救助空间里的对象还不应该被移动到年老代,但年轻代又有很多对象需要放入救助空间;第二个原因是年老代没有足够的空间接纳来自年轻代的对象;这两种情况都会转向Full GC,网站停顿时间较长。

解决方方案一

第一个原因我的最终解决办法是去掉救助空间,设置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0即可,第二个原因我的解决办法是设置CMSInitiatingOccupancyFraction为某个值(假设70),这样年老代空间到70%时就开始执行CMS,年老代有足够的空间接纳来自年轻代的对象。

解决方案一的改进方案

又有改进了,上面方法不太好,因为没有用到救助空间,所以年老代容易满,CMS执行会比较频繁。我改善了一下,还是用救助空间,但是把救助空间加大,这样也不会有promotion failed。具体操作上,32位Linux和64位Linux好像不一样,64位系统似乎只要配置MaxTenuringThreshold参数,CMS还是有暂停。为了解决暂停问题和promotion failed问题,最后我设置-XX:SurvivorRatio=1 ,并把MaxTenuringThreshold去掉,这样即没有暂停又不会有promotoin failed,而且更重要的是,年老代和永久代上升非常慢(因为好多对象到不了年老代就被回收了),所以CMS执行频率非常低,好几个小时才执行一次,这样,服务器都不用重启了。

-Xmx4000M -Xms4000M -Xmn600M -XX:PermSize=500M -XX:MaxPermSize=500M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log

CMSInitiatingOccupancyFraction值与Xmn的关系公式

上面介绍了promontion faild产生的原因是EDEN空间不足的情况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的情况下产生了promontion faild从而导致full gc.那可以推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的情况,即:
(Xmx-Xmn)*(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2)) 进而推断出:

CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)*100 

例如:

当xmx=128 xmn=36 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-36)-(36-36/(1+2)))/(128-36)*100 =73.913 

当xmx=128 xmn=24 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-24)-(24-24/(1+2)))/(128-24)*100=84.615… 

当xmx=3000 xmn=600 SurvivorRatior=1时  CMSInitiatingOccupancyFraction<=((3000.0-600)-(600-600/(1+2)))/(3000-600)*100=83.33

CMSInitiatingOccupancyFraction低于70% 需要调整xmn或SurvivorRatior值。

令:

网上一童鞋推断出的公式是::(Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100>=Xmn 这个公式个人认为不是很严谨,在内存小的时候会影响xmn的计算。

おすすめ

転載: blog.51cto.com/14309075/2415294