JVM GC的一些思考

GC是一個老生常談的問題,但是從現在的開發角度看GC帶來的意義是什麼,是硬件的上限難以提高,從軟件的角度上,來提高硬件的使用率
JVM的GC其實一直都是在內存的整理效果和GC造成的CPU時間損失中博弈。
所以帶來了不同的GC收集器

新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
整堆收集器: G1 ZGC
幾個相關概念:
並行收集:指多條垃圾收集線程並行工作,但此時用戶線程仍處於等待狀態。
併發收集:指用戶線程與垃圾收集線程同時工作(不一定是並行的可能會交替執行)。用戶程序在繼續運行,而垃圾收集程序運行在另一個CPU上。
吞吐量:即CPU用於運行用戶代碼的時間與CPU總消耗時間的比值(吞吐量 = 運行用戶代碼時間 / ( 運行用戶代碼時間 + 垃圾收集時間 ))。例如:虛擬機共運行100分鐘,垃圾收集器花掉1分鐘,那麼吞吐量就是99%
FULL GC,串行垃圾回收會使用應用停頓,響應用戶時間長

以前的常用幾種GC可以看這篇文章
https://www.cnblogs.com/chenpt/p/9803298.html
最新的ZGC可以看這篇
https://www.colabug.com/2020/0114/6846387/amp/
這裏我主要是來測試一下各種GC的不同效果。
G1GC,的確性能會好很多,YGC太久也會涼,FGC太久也會涼。感覺咋都涼,哈哈。
代碼在最後面
jvm配置爲

-Xms16m -Xmx32m -XX:+PrintCommandLineFlags

當前默認結果

-XX:InitialHeapSize=16777216 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

可以看到是ParalleGC的結果
現在結果就是7S FGC 36次 YGC 26528次
在這裏插入圖片描述

我現在增加 -XX:+UseParNewGC 看看
現在結果就是14S FGC 0次 YGC 58469次
在這裏插入圖片描述
-XX:+UseParallelGC:選擇垃圾收集器爲並行收集器。此配置僅對年輕代有效。可以同時並行多個垃圾收集線程,但此時用戶線程必須停止。( 關注吞吐量)

-XX:+UseParNewGC:設置年輕代爲多線程收集。可與CMS收集同時使用。在serial基礎上實現的多線程收集器。(關注響應時間)

使用 -XX:+UseParallelOldGC 配置

結果 FGC36次 YGC26527 總共6.8S 大概和之前的ParalleGC差不多,這也和定義相差不大,只是FGC多線程,也可能是我CPU多核性能更好。
在這裏插入圖片描述
最基礎的CMS配置
-XX:+UseConcMarkSweepGC

-XX:InitialHeapSize=16777216 -XX:MaxHeapSize=33554432 -XX:MaxNewSize=11186176 -XX:MaxTenuringThreshold=6 -XX:NewSize=11186176 -XX:OldPLABSize=16 -XX:OldSize=22368256 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC

結果FGC 0 YGC 29644,總共7.5S
在這裏插入圖片描述
G1GC
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

-XX:InitialHeapSize=16777216 -XX:MaxHeapSize=33554432 -XX:+PrintCommandLineFlags -XX:+UnlockExperimentalVMOptions -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation

結果FGC0 YGC13927 6.468s,性能暫時顯示最好
在這裏插入圖片描述


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import javax.smartcardio.CardTerminal;
import java.lang.reflect.Method;
import java.util.HashMap;

public class JvmGCTest {
    public static void main(String[] args) throws Exception {
        JvmGCTest jmTest = new JvmGCTest();
        jmTest.outOfMemoryTest();//out memory

    }


    public  void outOfMemoryTest() throws InterruptedException {

        for(int threadCount=0;threadCount<10;threadCount++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    int i = 0;
                    while (true) {
                        HashMap<String, TestNoStaticObject> map = new HashMap<>();
                        //System.out.println(i);
                        map.put(String.valueOf(i), new TestNoStaticObject());
                        i++;
                        if(i>=100000000){
                            break;
                        }
                        if (i <= 100) {
                            try {
                                Thread.sleep(100);
                            } catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }).start();
        }

    }

    public class TestNoStaticObject {
        private double a = 34.53;
        private Integer b = 9999999;

        public TestNoStaticObject() {
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章