天天看點

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

1 降低對象大小

能用基本類型就不用包裝類

懂得都懂。

應該定義成類變量的不要定義為執行個體變量

  • 一個類 =》 一個類變量
  • 一個執行個體 =》一個執行個體變量
  • 一個類 =》 多個執行個體
  • 執行個體越多,浪費越多

當然 netty 會結合這兩點!

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

2 預估配置設定的記憶體

  • 對已可預知固定size的HashMap避免擴容

提前計算好初始size或者直接使用

com.google.common.collect.Maps#newHashMapWithExpectedSize

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
  • 根據接受到的資料動态調整(guess) 下個要配置設定的Buffer的大小,比如

    io.netty.channel.AdaptiveRecvByteBufAllocator

3 零拷貝

邏輯組合代替實際複制

  • CompositeByteBuf
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

包裝替代實際複制

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

JDK的零拷貝接口

Netty 通過在 DefaultFileRegion 包裝了 NIO 的 FileChannel.transferTo() 實作零拷貝:іо.nеttу.сhаnnеl.DеfаultFіlеRеgіоn#trаnѕfеrТо

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

4 堆外記憶體

堆外記憶體生活場景:

燒烤店熱季時人滿為患,店家就會在門口加擺一些桌子招待新客人。

店内 =》 JVM内部 =》堆(heap) +非堆(non heap)

店外 =》 JVM外部 =》堆外(off heap)

優點

  • 更廣闊的“空間”,緩解店鋪内壓力->破除堆空間限制,減輕GC壓力
  • 減少“備援”細節(燒烤過程是在室外進行的:烤好直接上桌 V.S 烤好還要

    進店内) =》避免複制

缺點

  • 需要搬桌子 =》建立速度稍慢
  • 受城管監管、風險大 =》堆外記憶體受 os 管理

源碼

  • 堆外記憶體/堆内記憶體的預設選擇
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
  • 切換方式
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

堆外記憶體的配置設定本質

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
  • 可見依舊調用的 JDK 原生的堆外記憶體實作。
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

5 記憶體池

記憶體池生活場景:

點菜單的演進

一張紙:一桌客人一張紙

點菜平闆:循環使用

為何使用記憶體池

  • 建立對象開銷大

    比如堆外記憶體就是這樣

  • 對象高頻率建立且可複用
  • 支援并發又能保護系統
  • 維護、共享有限的資源

實作記憶體池

  • 開源實作:Apache Commons Pool

    程式共享,記憶體競争較嚴重

  • Netty輕量級對象池實作io.netty.util.Recycler

    基于特定場景才建立

記憶體池/非記憶體池的配置切換

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池

根據參數配置判定(切換方式二)

深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池
深入Netty源碼解析記憶體優化技巧1 降低對象大小2 預估配置設定的記憶體3 零拷貝4 堆外記憶體5 記憶體池