精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

談JVM xmx, xms等內存相關參數合理性設置

京東云 ? 來源:京東零售 劉樂 ? 作者:京東零售 劉樂 ? 2024-10-10 14:42 ? 次閱讀

作者:京東零售 劉樂

上一篇文章說到JVM垃圾回收算法的兩個優化標的:吞吐量和停頓時長,并提到這兩個優化目標是有沖突的。那么有沒有可能提高吞吐量而不影響停頓時長,甚至縮短停頓時長呢?答案是有可能的,提高內存占用(Memory Footprint)就有可能同時優化這兩個標的,這篇文章就來聊聊內存相關內容。

內存占用一般指應用運行需要的所有內存,包括堆內內存(On-heap Memory)和堆外內存(Off-heap Memory)

1. 堆內內存

堆內內存是分配給JVM的部分內存,用來存放所有Java Class對象實例和數組,JVM GC操作的就是這部分內容。我們先來回顧一下堆內內存的模型:

堆內內存包括年輕代(淺綠色),老年代(淺藍色),在JDK7或者更老的版本,圖中右邊還有個永久代(永久代在邏輯上位于JVM的堆區,但又被稱為非堆內存,在JDK8中被元空間取代)。JVM有動態調整內存策略,通過-Xms,-Xmx 指定堆內內存動態調整的上下限。 在JVM初始化時實際只分配部分內存,可通過-XX:InitialHeapSize指定初始堆內存大小,未被分配的空間為圖中virtual部分。年輕代和老年代在每次GC的時候都有可能調整大小,以保證存活對象占用百分比在特定閾值范圍內,直到達到Xms指定的下限或Xms指定的上限。(閾值范圍通過-XX:MinHeapFreeRatio, XX:MaxHeapFreeRatio指定,默認值分別為40, 70)。

GC調優中還有個的重要參數是老年代和年輕代的比例,通過-XX:NewRatio設定,與此相關的還有-XX:MaxNewSize和-XX:NewSize,分別設定年輕代大小的上下限,-Xmn則直接指定年輕代的大小。

1.1 參數默認值

?-Xmx: Xmx的默認值比較復雜,官方文檔上有時候寫的是1GB,但實際值跟JRE版本、JVM 模式(client, server)和系統(平臺類型,32位,64位)等都有關。經過查閱源碼和實驗,確定在生產環境下(server模式,64位Centos,JRE 8),Xmx的默認值可以采用以下規則計算:

?容器內存小于等于2G:默認值為容器內存的1/2,最小16MB, 最大512MB。

?容器內存大于2G:默認值為容器內存的1/4, 最大可到達32G。

?-Xms: 默認值為容器內存的1/64, 最小8MB,如果明確指定了Xmx并且小于容器內存1/64, Xms默認值為Xmx指定的值。

?-NewRatio: 默認2,即年輕代和年老代的比例為1:2, 年輕代大小為堆內內存的1/3。

NOTE:在JRE版本1.8.0_131之前,JVM無法感知Docker的資源限制,Xmx, Xms未明確指定時,會使用宿主機的內存計算默認值。

1.2 最佳實踐

由于每次Eden區滿就會觸發YGC,而每次YGC的時候,晉升到老年代的對象大小超過老年代剩余空間的時候,就會觸發FGC。所以基本來說,GC頻率和堆內內存大小是成反比的,也就是說堆內內存越大,吞吐量越大。

如果Xmx設置過小,不僅浪費了容器資源,在大流量下會頻繁GC,導致一系列問題,包括吞吐量降低,響應變長,CPU升高,java.lang.OutOfMemoryError異常等。當然Xmx也不建議設置過大,否則會導致進程hang住或者使用容器Swap。所以合理設置Xmx非常重要,特別是對于1.8.0_131之前的版本,一定要明確指定Xmx。推薦設置為容器內存的50%,不能超過容器內存的80%。

JVM的動態內存策略不太適合服務使用,因為每次GC需要計算Heap是否需要伸縮,內存抖動需要向系統申請或釋放內存,特別是在服務重啟的預熱階段,內存抖動會比較頻繁。另外,容器中如果有其他進程還在消費內存,JVM內存抖動時可能申請內存失敗,導致OOM。因此建議服務模式下,將Xms設置Xmx一樣的值。

NewRatio建議在2~3之間,最優選擇取決于對象的生命周期分布。一般先確定老年代的空間(足夠放下所有live data,并適當增加10%~20%),其余是年輕代,年輕代大小一定要小于老年代。

另外,以上建議都是基于一個容器部署一個JVM實例的使用情況。有個別需求,需要在一個容器內啟用多個JVM,或者包含其他語言的,研發需要按業務需求在推薦值范圍內分配JVM的Xmx。

2. 堆外內存

和堆內內存對應的就是堆外內存。堆外內存包括很多部分,比如Code Cache, Memory Pool,Stack Memory,Direct Byte Buffers, Metaspace等等,其中我們需要重點關注的是Direct Byte Buffers和Metaspace。

2.1 Direct Byte Buffers

Direct Byte Buffers是系統原生內存,不位于JVM里,狹義上的堆外內存就是指的Direct Byte Buffers。為什么要使用系統原生內存呢? 為了更高效的進行Socket I/O或文件讀寫等內核態資源操作,會使用JNI(Java原生接口),此時操作的內存需要是連續和確定的。而Heap中的內存不能保證連續,且GC也可能導致對象隨時移動。因此涉及Output操作時,不直接使用Heap上的數據,需要先從Heap上拷貝到原生內存,Input操作則相反。因此為了避免多余的拷貝,提高I/O效率,不少第三方包和框架使用Direct Byte Buffers,比Netty。

Direct Byte Buffers雖然有上述優點,但使用起來也有一定風險。常見的Direct Byte Buffers使用方法是用java.nio.DirectByteBuffer的unsafe.allocateMemory方法來創建,DirectByteBuffer對象只保存了系統分配的原生內存的大小和啟始位置,這些原生內存的釋放需要等到DirectByteBuffer對象被回收。有些特殊的情況下(比如JVM一直沒有FGC,設置-XX:+DisableExplicitGC禁用了System.gc),這部分對象會持續增加,直到堆外內存達到-XX:MaxDirectMemorySize 指定的大小或者耗盡所有的系統內存。

MaxDirectMemorySize不明確指定的時候,默認值為0,在代碼中實際為Runtime.getRuntime().maxMemory(),略小于-Xmx指定的值(堆內內存的最大值減去一個Survivor區大?。?。此默認值有點過大,MaxDirectMemorySize未設置或設置過大,有可能發生堆外內存泄露,導致進程被系統Kill。

由于存在一定風險,建議在啟動參數里明確指定-XX:MaxDirectMemorySize的值,并滿足下面規則:

?Xmx * 110% + MaxDirectMemorySize + 系統預留內存 <= 容器內存

?Xmx * 110% 中額外的10%是留給其他堆外內存的,是個保守估計,個別業務運行時線程較多,需自行判斷,上式中左側還需加上Xss * 線程數

?系統預留內存512M到1G,視容器規格而定

?I/O較多的業務適當提高MaxDirectMemorySize比例

2.2 Metaspace

Metaspace(元空間)是JDK8關于方法區新的實現,取代之前的永久代,用來保存類、方法、數據結構等運行時信息和元信息的。很多研發在老版本時可能遇到過java.lang.OutOfMemoryError: PermGen Space,這說明永久代的空間不夠用了,JDK7以前可以通過-XX:PermSize,-XX:MaxPermSize來指定永久代的初始大小和最大大小。JDK8中Metaspace取代永久代,位置由JVM內存變成系統原生內存,也取消默認的最大空間限制。與此有關的參數主要有下面兩個:

?-XX:MaxMetaspaceSize 指定元空間的最大空間,默認為容器剩余的所有空間

?-XX:MetaspaceSize 指定元空間首次擴充的大小,默認為20.8M

由于MaxMetaspaceSize未指定時,默認無上限,所以需要特別關注內存泄露的問題,如果程序動態的創建了很多類,或出現過java.lang.OutOfMemoryError:Metaspace,建議明確指定-XX:MaxMetaspaceSize。另外Metaspace實際分配的大小是隨著需要逐步擴大的,每次擴大需要一次FGC,-XX:MetaspaceSize默認的值比較小,需要頻繁GC擴充到需要的大小。通過下面的日志可以看到Metaspace引起的FGC:

[Full GC (Metadata GC Threshold) ...]

為減少預熱影響,可以將-XX:MetaspaceSize,-XX:MaxMetaspaceSize指定成相同的值。另外不少應用由JDK7升級到了JDK8,但是啟動參數中仍有-XX:PermSize,-XX:MaxPermSize,這些參數是不生效的,建議修改成-XX:MetaspaceSize,-XX:MaxMetaspaceSize。

3. 應用健康度檢查規則

?泰山應用健康度現在已支持掃描JVM相關風險,在應用TAB的JVM配置檢測項下。主要包括以下檢測:

檢測指標 風險等級 巡檢規則
JVM版本 中危 版本不低于1.8.0_191
JVM GC方法 中危 所有分組GC方法一致
Xmx 高危 明確指定,并且在容器內存的50%~80%范圍內
Xms 中危 明確指定,并且等于Xmx指定的值
堆外內存 中危 明確指定,并且 堆內*1.1+堆外+系統預留<=容器內存
ParallelGCThreads 高危 ParallelGCThreads在容器CPU核數的50%~100%范圍內
ConcGCThreads 低危 ConcGCThreads在ParallelGCThreads的20%~50%范圍內(限CMS,G1)
CICompilerCount 低危 指定CICompilerCount在推薦值50%~150%內(限1.8

?上一篇文章已經說了ParallelGCThreads,這里再補充一下新支持的兩個檢測,ConcGCThreads,CICompilerCount。

ConcGCThreads一般稱為并發標記線程數,為了減少GC的STW的時間,CMS和G1都有并發標記的過程,此時業務線程仍在工作,只是并發標記是CPU密集型任務,業務的吞吐量會下降,RT會變長。ConcGCThreads的默認值不同GC策略略有不同,CMS下是(ParallelGCThreads + 3) / 4 向下取整,G1下是ParallelGCThreads / 4 四舍五入。一般來說采用默認值就可以了,但是還是由于在JRE版本1.8.0_131之前,JVM無法感知Docker的資源限制的問題,ConcGCThreads的默認值會比較大(20左右),對業務會有影響。

CICompilerCount是JIT進行熱點編譯的線程數,和并發標記線程數一樣,熱點編譯也是CPU密集型任務,默認值為2。在CICompilerCountPerCPU開啟的時候(JDK7默認關閉,JDK8默認開啟),手動指定CICompilerCount是不會生效的,JVM會使用系統CPU核數進行計算。所以當使用JRE8并且版本小于1.8.0_131,采用默認參數時,CICompilerCount會在20左右,對業務性能影響較大,特別是啟動階段。建議升級Java版本,特殊情況要使用老版本Java 8,請加上-XX:CICompilerCount=[n], 同時不能指定-XX:+CICompilerCountPerCPU ,下表給出了生產環境下常見規格的推薦值。

容器CPU核數 1 2 4 8 16
CICompilerCount手動指定推薦值 2 2 3 3 8

4. 修改建議

1) 再次建議升級JRE版本到1.8.0_191及以上; 2) 建議在Shell腳本中,Export JAVA_OPTS環境變量, 至少包含以下幾項(方括號中的值根據文中推薦選取):

-server -Xms[8192m] -Xmx[8192m] -XX:MaxDirectMemorySize=[4096m]

如果特殊原因要使用1.8.0_131以下版本, 則同時需要加上以下參數(方括號中的值根據文中推薦選取):

-XX:ParallelGCThreads=[8] -XX:ConcGCThreads=[2] -XX:CICompilerCount=[2]

下面的項建議測試后使用,需自行確定具體大小(特別是使用JRE8但仍配置-XX:PermSize,-XX:MaxPermSize的應用):

-XX:MaxMetaspaceSize=[256]m -XX:MetaspaceSize=[256]m

環境變量設置如下例子:

export JAVA_OPTS="-Djava.library.path=/usr/local/lib -server -Xms4096m -Xmx4096m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:MaxDirectMemorySize=2048m -XX:ParallelGCThreads=8 -XX:ConcGCThreads=2 -XX:CICompilerCount=2 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs -XX:+UseG1GC [other_options...] -jar jarfile [args...]"

另外,如果應用未接入UMP或PFinder, JAVA_OPTS中盡量不要用Shell函數或者變量,否則健康度有可能會提示解析失敗。

NOTE: Java options 的使用應該按照下面的順序:

?執行類: java [-options] class [args...]

?執行包:java [-options] -jar jarfile [args...] 或 java -jar [-options] jarfile [args...]

即options要放到執行對象之前,部分應用使用了以下順序:

java -jar jarfile [-options] [args...] 或者 java -jar jarfile [args...] [-options]

這些Java options都不會生效。

修改補充說明:

上面的JVM參數配置已經集成到行云部署了,在行云部署-分組-配置管理-JVM參數配置,點填充就可以配置默認的JVM參數,如有需要也可以對特定的參數進行修改,注意worker類型應用需要在啟動腳本(start.sh)中增加如下行:

source /home/admin/default_vm.sh

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    8

    文章

    3002

    瀏覽量

    73887
  • JVM
    JVM
    +關注

    關注

    0

    文章

    157

    瀏覽量

    12209
  • xmxl
    +關注

    關注

    0

    文章

    2

    瀏覽量

    1237
收藏 人收藏

    評論

    相關推薦

    容器JVM內存配置最佳實踐

    Killer)機制,此時系統會終止內存占用較多的進程以保證系統的正常運行。特別是在容器環境下,不合理JVM參數設置會導致各種異?,F象產生,例如應用堆大小還未到達
    發表于 06-20 09:45 ?860次閱讀
    容器<b class='flag-5'>JVM</b><b class='flag-5'>內存</b>配置最佳實踐

    求助,TC375的時鐘合理性檢查用哪個外設才能實現?

    基本思路是通過外設產生定時中斷,來反推外設本身的時鐘頻率。但是QSPI和ADC這些外設目前不能使用,也不太好用,那么要用其余的哪個外設來實現這個Fppl1的合理性檢查呢?
    發表于 02-06 07:38

    關于改進matlab中存儲方法的一個帖子,有個問題請教一下

    for versions of the JVM:JVM Initial Heap Size Max Heap Size1.6.0 -Xms64m -Xmx128m (32-bit)-
    發表于 06-14 16:08

    三極管接法是否有更具合理性的方式

    關于三極管的3種基礎接法比較,這是一個基礎但很多工程師常常疏忽的問題,乃至于在平常的應用中,你可能不會考慮三極管接法是否有更具合理性的方式,而在面試題中,這樣的題目可能直接成了一道“啞題”...
    發表于 01-18 08:04

    密碼協議形式化分析的計算合理性

    基于Abadi-Rowgaway 的形式化加密的計算合理性定理,論文提出和證明了密碼協議形式化分析的計算合理性定理。通過對群密鑰分配協議的分析,說明本文的定理對協議的可選擇攻擊具
    發表于 06-06 13:49 ?11次下載

    地面數據模擬計算風能參數合理性分析_高健

    地面數據模擬計算風能參數合理性分析_高健
    發表于 12-30 15:05 ?0次下載

    jvm調優參數

    和類元數據等方面的參數設置。下面我們將詳細介紹這些參數以及如何進行優化。 首先,堆內存JVM中用于存放對象實例的內存區域。通過調整堆
    的頭像 發表于 12-05 11:29 ?601次閱讀

    jvm參數設置jvm調優

    JVM(Java虛擬機)參數設置和調優對于提高Java應用程序的性能和穩定性非常重要。在本文中,我們將詳細介紹JVM參數
    的頭像 發表于 12-05 11:36 ?1437次閱讀

    jvm調優主要是調哪里

    ,棧內存存儲方法調用和局部變量,非堆內存用于存儲加載的類信息以及一些靜態變量。 1.1 堆內存調優 堆內存
    的頭像 發表于 12-05 11:37 ?1528次閱讀

    jvm調優常用命令

    JVM調優是提升Java應用性能的一個重要方面,通過合理設置JVM參數可以達到優化應用性能、提高系統穩定性的目的。本文將為你詳細介紹
    的頭像 發表于 12-05 11:43 ?664次閱讀

    jvm配置堆內存初始值參數

    程序中,堆內存的初始值是非常重要的,它決定了程序在運行過程中能夠使用的內存大小。因此,在優化JVM性能的過程中,對于堆內存初始值的合理配置是
    的頭像 發表于 12-05 14:17 ?738次閱讀

    jvm配置metaspace最大值的參數

    內存限制):該參數用于設置JVM堆的最大大小。在JVM啟動時,可以使用以下命令來配置Metaspace的最大大小: java -
    的頭像 發表于 12-05 14:21 ?2018次閱讀

    weblogic jvm參數配置

    ,讓我們來了解一些常用的JVM參數: -Xms 和 -Xmx參數:這些參數分別用于
    的頭像 發表于 12-05 14:31 ?1371次閱讀

    weblogic設置jvm內存大小

    WebLogic是一種Java EE應用服務器,用于構建和部署企業級Java應用程序。在配置WebLogic服務器時,設置JVM內存大小非常重要,這可以提高應用程序的性能和可靠性。本文將詳細介紹
    的頭像 發表于 12-05 14:44 ?2978次閱讀

    eclipse設置jvm內存大小

    內存大小,并對其背后的原理進行解釋。 JVM(Java虛擬機)是Java程序的運行環境,它負責將Java字節碼翻譯成機器碼,以便在不同的平臺上執行。JVM使用內存來存儲運行時對象和執行
    的頭像 發表于 12-06 11:43 ?1827次閱讀