1. 程式人生 > >Java性能權威指南讀書筆記--之二

Java性能權威指南讀書筆記--之二

任務 觸發 ber vivo 日誌 普通 參數 成對 初始

新生代填滿時,垃圾收集器會暫停所有的應用線程,回收新生代空間。這種操作被稱為Minor GC。
老年代被填滿時,垃圾收集器會暫停所有應用線程,對其進行回收,接著對堆空間進行整理。這個過程被稱為Full GC。
最主流的四個垃圾收集器分別是:Serial收集器、Throughput(或者Parallel)收集器、Concurrent(CMS、G1)垃圾收集器。Concurrent垃圾收集器可以通過復雜的計算,可以在應用線程運行的同時找出不再使用的對象。
使用CMS或G1收集器時,應用程序精力的停頓會更少,所帶來的代價是消耗更多的CPU。
評估垃圾收集器時,應考慮以下幾點:

  • 如果要盡可能地縮短相應時間,那麽選擇使用Concurrent收集器更合適
  • 如果平均相應時間比最大響應時間更重要,那麽應該使用Parallel收集器
  • 使用Concurrent收集器來避免長時間停頓時間也有其代價,這會消耗額外的CPU
    • 如果CPU足夠強勁,使用Concurrent收集器避免發生Full GC可以讓任務運行得更快
    • 如果CPU資源有限,那麽Concurrent收集器額外的CPU消耗會使批量任務消耗更多的時間

GC算法

  1. Serial垃圾收集器
    使用單線程清理堆的內容。進行Full GC時,它還會對老年代空間的對象進行壓縮整理。通過-XX:+UseSeralGC標誌可以啟用Serial收集器
  2. Parallel收集器
    Parallel收集器可以使用多線程對堆空間進行回收。在MinorGC和FullGC時會暫停所有的應用線程,同事在FullGC過程中會對老年代空間進行壓縮整理。通過-XX:+UseParallelOldGC標誌可以開啟這個功能。
  3. CMS收集器
    CMS收集器在MinorGC時會暫停所有的應用線程,並以多線程的方式進行垃圾回收(-XX:UseParNewGC)。CMS收集器在進行FullGC時不再暫停應用線程,而是使用若幹個後臺線程定期地對老年代空間進行掃描, 及時回收其中不在使用的對象,並且後臺線程不在進行任何壓縮整理的工作。如果堆的碎片化過於嚴重CMS收集器會暫停所有應用線程,使用單線程回收、整理老年代空間(-XX:UseConcMarkSweepGC)。
  4. G1垃圾收集器
    G1收集算法將堆劃分為若幹個區域,新生代的垃圾收集仍然采用暫停所有應用線程的方式,將存貨對象移動到老年代或者Servivor空間。老年代的垃圾收集工作由後臺線程完成,由於老年代被劃分到不同的區域,G1收集器通過將對象從一個區域復制到另一個區域,完成對象的清理工作,同時在進行了堆的壓縮整理(-XX:+UseG1GC)。

選擇GC算法

如果有額外的CPU處理能力,那麽使用Concurrent收集器將極大地提升應用程序的性能。
通常情況下,parallel收集器的平均響應時間比Concurrent收集器要差,但是在90%響應時間或者99%響應時間這幾項指標上,parallel收集器比Concurrent收集器要好一些。
使用parallel收集器會超負荷地進行大量Full GC時,切換到Concurrent收集器通常能獲得更低的響應時間。
一般情況下,堆空間小於4GB時,CMS收集器的性能比G1收集器好。
G1的設計使得它能夠在不同的分區處理堆,因此它的擴展性更好,比CMS更易於處理超大堆的情況。

調整堆的大小

通常情況下,對於普通的操作系統,應該預留至少1G的內存空間。
堆的大小由2個參數值控制:分別是初始值(通過 -Xms N設置)和最大值(通過-Xms N設置)。
如果確切地了解應用程序需要多大的堆,那麽可以將堆的初始值和最大值直接設置成對應的數據(譬如:-Xms4096m -Xmx4096m)。這種設置能稍微提高GC的運行效率,因為它不再需要估算堆是否需要調整大小了。
任何事情都有兩面性,如果新生代分配得比較大,垃圾收集發生的頻率就比較低,從新生代晉升到老年代的對象也更少,但是老年代就相對比較小,比較容易被填滿,會更頻繁的觸發Full GC。
所有用於調整代空間的命令行標誌調整的都是新生代空間;新生代空間剩下的所有空間都被老年代占用。
-XX:NewRatio=N
設置新生代與老年代的空間占用比率
-XX:NewSize=N
設置新生代空間的初始大小
-XX:MaxNewSize=N
設置新生代空間的最大大小
-XmnN
將NewSize和MaxNewSize設定為同一個值的快捷方法
最初的新生代的大小由NewRatio的決定,默認值為2.
Initial Young Get Size = Initial Heap Size/(1 + NewRatio)
新生代空間的大小是初始堆大小的33%
多線程的垃圾收集器算法是由-XX:ParallelGCThreads=N參數控制
總的垃圾收集器線程數 = 8 + (N - 8)* 5/8
有時候垃圾收集線程需要調整,例如在128C的機器上使用一個1G的堆,那麽會啟動83個線程,明顯就偏大了;又如在16C的機器同時運行4個JVM實例,那麽每個JVM會啟動13個垃圾收集器線程,總共會有52個垃圾收集器線程,這樣會導致大量沖突,那麽將每個JVM的垃圾收集器限制為4個是一個比較合理的平衡。

垃圾回收工具

-XX:+PrintGCDetails
創建詳細的GC日誌
-XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps
GC時發生的日期,可以配合上面的參數使用
-Xloggc:filename,可以配合上面的參數使用
修改GC日誌輸出到某個文件
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=N
-XX:GCLogFileSize=N
可以控制日誌文件的循環。NumberOfGCLogFiles產生日誌的個數,GCLogFileSize日誌的大小

Java性能權威指南讀書筆記--之二