netty知识点

69 阅读2分钟

背景

内存管理介绍

内存管理的目的是合理分配内存,减少内存碎片,及时回收资源,提高内存的使用资源。

可以带着以下问题进行研究:

  • 内存池管理算法是如何实现高效内存分配释放,减少内存碎片?
  • 高负载下内存池不断申请/释放,如何实现弹性伸缩?
  • 内存池作为全局数据,在多线程环境下如何减少锁竞争?

常见的一些算法有slab,buddy,jemalloc等经典算法。

Netty中的内存管理应该是借鉴了FreeBSD内存管理的思想——jemalloc。Netty内存分配过程中总体遵循以下规则:

  • 优先从缓存中分配
  • 如果缓存中没有的话,从内存池看看有没有剩余可用的
  • 如果已申请的没有的话,再真正申请内存
  • 分段管理,每个内存大小范围使用不同的分配策略
  • 内存分享

Netty根据每次请求分配内存的大小,将请求分为如下几类:

分类说明对应代码
tiny16的倍数 小于 512b
small512b的倍数 小于等于4096b
normal8192倍数 小于16m
huge大于16m
 int normalizeCapacity(int reqCapacity) {
        if (reqCapacity < 0) {
            throw new IllegalArgumentException("capacity: " + reqCapacity + " (expected: 0+)");
        }

        if (reqCapacity >= chunkSize) {
            return directMemoryCacheAlignment == 0 ? reqCapacity : alignCapacity(reqCapacity);
        }

       // 判断是否小于512b 判断算法是 (reqCapacity & 0xFFFFFE00) == 0; 0xFFFFFE00 = -512
        if (!isTiny(reqCapacity)) { // >= 512
           // 如果申请的内存大于512则规范化为大于reqCapacity的最近的2的指数次的值
            int normalizedCapacity = reqCapacity;
            normalizedCapacity --;
            normalizedCapacity |= normalizedCapacity >>>  1;
            normalizedCapacity |= normalizedCapacity >>>  2;
            normalizedCapacity |= normalizedCapacity >>>  4;
            normalizedCapacity |= normalizedCapacity >>>  8;
            normalizedCapacity |= normalizedCapacity >>> 16;
            normalizedCapacity ++;

            if (normalizedCapacity < 0) {
                normalizedCapacity >>>= 1;
            }
            assert directMemoryCacheAlignment == 0 || (normalizedCapacity & directMemoryCacheAlignmentMask) == 0;

            return normalizedCapacity;
        }

        if (directMemoryCacheAlignment > 0) {
            return alignCapacity(reqCapacity);
        }
       下面之所以是16的倍数是因为用来管理tiny内存tinySubpagePools数组的大小刚好是512>>>432个元素
       每个元素PoolSubpage本身会构成链表,也就是说每个元素(PoolSubpage)对应的链表内每个元素的内存块大小(elemSize)是相同的,数组内每个链表的elemSize依次是:
       16,32,48......480496512


        // 刚好是16的倍数 直接返回
        if ((reqCapacity & 15) == 0) {
            return reqCapacity;
        }

        return (reqCapacity & ~15) + 16;
    }

flink

org.apache.flink.runtime.io.network.netty.NettyServer

spark

org.apache.spark.network.server.TransportServer

参考:

docs.google.com/document/d/…