天天看點

通用池化架構GenericObjectPool性能測試

之前寫過了- 通用池化架構commons-pool2實踐以及通用池化架構實踐之GenericKeyedObjectPool。接下來我就對這個池化架構進行性能測試。首先呢就是因為這個池化技術必需要有足夠的性能,不然通過池化技術優化的部分,在較高QPS的性能測試中,對象池可能成為本機瓶頸。

硬體軟體配置

硬體就是我自己的電腦,型号

MacBook Pro (16-inch, 2019)

,配置

6C16G

。因為這次測試并沒有測試到性能極限,在測試方案設計的前階段已經有了相對明顯的結論了。

軟體方面,還是Groovy,預設Java程序啟動參數。對象池化的設定後面可以在代碼中看到,經過我的測試,隻要對象池中還有空閑對象就足夠滿足目前性能。因為我本次用的是固定線程模型,是以換算過來就是對象數大于線程數即可。

測試前準備

測試分成了兩部分:無等待歸還對象、有等待歸還對象。因為無等待歸還對象測試過程中,結論出現的太早也太明顯了。

可池化對象

/**
     * 可池化對象
     */
    private static class FunTesterPooled {

        String name

        int age

    }

           

池化工場

/**
     * 池化工廠
     */
    private static class FunFactory extends BasePooledObjectFactory<FunTesterPooled> {


        @Override
        FunTesterPooled create() throws Exception {
            return new FunTesterPooled()
        }

        @Override
        PooledObject<FunTesterPooled> wrap(FunTesterPooled obj) {
            return new DefaultPooledObject<FunTesterPooled>(obj)
        }

        @Override
        void destroyObject(PooledObject<FunTesterPooled> p, DestroyMode destroyMode) throws Exception {
            p.getObject().setName("") //回收資源
            super.destroyObject(p, destroyMode)
        }
    }
           

對象池

static def initPool() {
        def config = new GenericObjectPoolConfig<FunTesterPooled>()
        config.setMaxIdle(10)
        config.setMinIdle(2)
        config.setMaxTotal(thread * 2)
        return new GenericObjectPool<FunTesterPooled>(new FunFactory(), config)
    }
           

性能測試用例

static GenericObjectPool<FunTesterPooled> pool

    static def desc = "池化架構性能測試"

    static int times = 3000000

    static int thread = 2

    public static void main(String[] args) {
        this.pool = initPool()
        ThreadBase.COUNT = true
        RUNUP_TIME = 0
        def barrier = new CyclicBarrier(thread + 1)
        POOL_SIZE = thread
        def borrows = []
        thread.times {
            fun {
                borrows << pool.borrowObject()
                barrier.await()
            }
        }
        barrier.await()
        borrows.each {
            pool.returnObject(it)
        }
        output("對象建立完畢 建立數量${pool.getNumIdle()}")
        new Concurrent(new FunTester(), thread, desc).start()
        pool.close()
    }

    private static class FunTester extends FixedThread {


        FunTester() {
            super(null, times, true)
        }

        @Override
        protected void doing() throws Exception {
            pool.returnObject(pool.borrowObject())
        }

        @Override
        FunTester clone() {
            return new FunTester()
        }
    }

           

其中往對象池中添加對象的時候,一開始我思路有點偏,是以想了一個

java.util.concurrent.CyclicBarrier

的方案。其實我們直接可以使用官方提供的

org.apache.commons.pool2.ObjectPool#addObjects

方法實作,代碼非常簡單,一行搞定

pool.addObjects(thread)

測試結果

無等待

線程數 執行次數(萬) QPS
1 300 1876172
2 300 1852364
5 300 1533912
10 300 1524538
10 100 1571623
20 100 1568692

可以看出,QPS非常高,足夠滿足線性能測試需求。

等待

線程數 執行次數(k) 單線程QPS
20 10 410
50 10 406
100 5 406
200 2 404
300 2 403
400 2 403
500 2 262
800 2 143
1000 2 114

繼續閱讀