PooledByteBufAllocator的坑——不一定会池化

2019-04-28  本文已影响0人  黄云斌huangyunbin

netty的PooledByteBufAllocator从名字上看就知道是使用池化内存,但其实在一些场景是不一定使用池化的。

1 jvm内存小于96M的时候,是不会使用池的
public static void main(String[] args) throws Exception {
        
        ByteBufAllocator byteBufAllocator = new PooledByteBufAllocator(false);
        for (int i = 0; i < 1000; i++) {
            ByteBuf buffer = byteBufAllocator.heapBuffer(1 * 1024 * 1024);
            System.out.println("分配了 " + 1 * (i + 1) + " MB");
            Thread.sleep(30);
        }
    }

使用jvm参数

-Xmx50m -Xms50m

会发现一直没爆内存:


image.png

这个是为什么呢:
断点的时候看到,根本就没有从池里分配内存


image.png

heapArena为什么是null呢?
是因为nHeapArena为0


image.png

nHeapArena是由DEFAULT_NUM_HEAP_ARENA决定的


image.png

核心逻辑是:

runtime.maxMemory() / defaultChunkSize / 2 / 3

defaultChunkSize 是16777216,就是16M
16Mx2x3=96M,也就是说 runtime.maxMemory()大于96M的时候,才会用到池化。

2 如果对象大于16M,也是不会使用池的
public static void main(String[] args) throws Exception {
        
        ByteBufAllocator byteBufAllocator = new PooledByteBufAllocator(false);
        for (int i = 0; i < 1000; i++) {
            ByteBuf buffer = byteBufAllocator.heapBuffer(20 * 1024 * 1024);
            System.out.println("分配了 " + 20 * (i + 1) + " MB");
            Thread.sleep(30);
        }
    }

使用参数:

-Xmx200m -Xms200m 

发现内存也是不会爆的。
这个是为什么呢,就是因为分配的内存大于了16M
PoolArena类的allocateHuge方法是直接分配Unpooled的内存的


image.png

为什么会走到allocateHuge呢?


image.png
16777216就是16M,所以是大于16M的时候就会这样了。
上一篇下一篇

猜你喜欢

热点阅读