什么是Java对象分配率?
類似“不可持續的內存分配率”和“你需要維持低的內存分配率”這樣的短語看起都像是屬于 Java 冠軍(Java Champions)的專有詞匯。復雜、嚇人、充滿神秘色彩。
這些詞語經常出現,但是如果你深入了解這些概念,它的神秘色彩就煙消云散了。這篇文章將試著揭開上面這些術語的神秘面紗。
什么是內存分配率?我們為什么要關心它?
內存分配率是指單位時間內分配內存的總數量,通常用 MB/sec 表示。不過,如果你樂意,也可以用 PB/year 來表示。這就是全部的內容——沒那么神秘,僅僅是指 Java 代碼在一定時期內內存分配的大小。
不過只知道這一點沒有太大的意義。如果你能忍受,我將帶你在實踐中應用這個概念。高分配率意味著你的程序存在性能問題。從實踐角度來說,主要影響是使得?GC(Garbage Collection)?成為了瓶頸。從硬件角度來說,即使常用的硬件也能支持每核幾 GB/sec 的分配率。而實際上,你的分配率不會超過 1 GB/sec/core。所以你可以放心,硬件基本不可能成為應用的瓶頸。
所以,當我們關注 GC 的時候,就可以和真實情況類比了——如果你創建很多的成員,之后就需要做很多清理工作。我們知道,JVM 建立垃圾回收機制需要知道內存分配率,由此來改變 GC 執行的頻率和 GC 停頓的時間。
內存分配率的測量
我們開始測量內存分配率。我們設置 JVM 參數:-XX:+PrintGCDetails -XX:+PrintGCTimeStamps 來打開 GC 日志。現在,JVM 開始以下列方式記錄 GC 停頓日志:
| 1 2 3 | 0.291: [GC (Allocation Failure) [PSYoungGen: 33280K->5088K(38400K)] 33280K->24360K(125952K),0.0365286secs] [Times: user=0.11sys=0.02, real=0.04secs] 0.446: [GC (Allocation Failure) [PSYoungGen: 38368K->5120K(71680K)] 57640K->46240K(159232K),0.0456796secs] [Times: user=0.15sys=0.02, real=0.04secs] 0.829: [GC (Allocation Failure) [PSYoungGen: 71680K->5120K(71680K)] 112800K->81912K(159232K),0.0861795secs] [Times: user=0.23sys=0.03, real=0.09secs] |
根據上述 GC 日志,我們可以從年青代(Young Generation)上一次回收后的大小及下一次回收前的大小來計算出分配率。利用上面的例子,我們可以抽取出如下信息:
- JVM 啟動291毫秒后,加載的對象大小是33280K。第一次 minor GC 清理后,年青代剩余的對象大小是 5088K。
- 啟動446毫秒后,年青代占用的空間已經增長到38368K,并觸發了下一次 GC,這次 GC 后,年青代占用的空間減少到5120K。
- 啟動829毫秒后,年青代的大小是71680K,GC 后再次減少到 5120K。
這些數據用如下的表格展示,計算出來的內存分配率添加年青代占用空間的后面:
| 1st GC | 291ms | 33,280KB | 5,088KB | 33,280KB | 114MB/sec |
| 2nd GC | 446ms | 38,368KB | 5,120KB | 33,280KB | 215MB/sec |
| 3rd GC | 829ms | 71,680KB | 5,120KB | 66,560KB | 174MB/sec |
| Total | 829ms | N/A | N/A | 133,120KB | 161MB/sec |
有了這些信息,我們就可以說對這個特定軟件,在測量期間的內存分配率是161 MB/sec。
影響分析
現在,通過這些信息,我們能夠明白改變內存分配率,可以增加或減少 GC 停頓的頻率,從而影響應用的吞吐率。首先,也是最重要的,你應該注意只有?Minor GC?清理年青代的停頓才會受影響。老年代(Old Generation)的清理,無論是頻率還是持續時間都不直接受分配率的影響,但是受增長率(promotion rate)的影響,增長率是下一篇文章討論的術語。
了解這些后,我們就只需要關注?Minor GC?的停頓,我們應該更進一步的去理解在年青代內部內存池的不同之處。因為內存分配是在 Eden 區中進行的,我們可以直接看 Eden 區的大小對分配率的影響。所以我們可以假設,隨著?Eden?區的增長,minor GC 停頓頻率頻率會降低,應用就能滿足更快的分配率。
事實上,當我們采用不同的 Eden 區大小(-XX:NewSize -XX:MaxNewSize 和 -XX:SurvivorRatio參數)來執行相同的實例時,我們可以看到兩種不同的內存分配率:
- 設置 Eden 區為100M,運行上面的例子,內存分配率降低到100MB/sec。
- 增加個 Eden 區到1GB,增加的內存分配率接近 200MB/sec。
如果你仍然疑惑這為什么是對的——假設減少應用線程 GC 的頻率,你就可以做更多的有用的工作。這樣就可以生成更多的對象,從而支持更高內存分配率。
現在,在你得出“ Eden 區越大越好”的結論之前,你應該注意內存分配率可能不會直接關聯應用的真實吞吐率。并且這只是一種側重吞吐率的技術測量。內存分配率只影響 Minor GC 暫停應用線程的頻率,但從整體的影響來說,你還需要考慮 Major GC 的停頓以及應用提供的業務操作。
原文鏈接:? plumbr ?翻譯:? ImportNew.com? -? paddx譯文鏈接:? http://www.importnew.com/16803.html 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的什么是Java对象分配率?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Spring Boot开发Web项目
- 下一篇: Quartz 入门详解