美文网首页
Netty源码分析(九) PoolSubpage

Netty源码分析(九) PoolSubpage

作者: skyguard | 来源:发表于2018-11-08 10:09 被阅读0次

前面我们介绍了PoolChunk和PoolChunkList,对于小内存(小于4096)的分配还会将Page细化成更小的单位Subpage。Subpage按大小分有两大类,tiny和small。下面就来介绍一下PoolSubpage。
先来看一下PoolSubpage有哪些属性

/**
 * 所属 PoolChunk 对象
 */
final PoolChunk<T> chunk;
/**
 * 在 {@link PoolChunk#memoryMap} 的节点编号
 */
private final int memoryMapIdx;
/**
 * 在 Chunk 中,偏移字节量
 *
 * @see PoolChunk#runOffset(int)
 */
private final int runOffset;
/**
 * Page 大小 {@link PoolChunk#pageSize}
 */
private final int pageSize;

/**
 * Subpage 分配信息数组
 *
 * 每个 long 的 bits 位代表一个 Subpage 是否分配。
 * 因为 PoolSubpage 可能会超过 64 个( long 的 bits 位数 ),所以使用数组。
 *   例如:Page 默认大小为 8KB ,Subpage 默认最小为 16 B ,所以一个 Page 最多可包含 8 * 1024 / 16 = 512 个 Subpage 。
 *        因此,bitmap 数组大小为 512 / 64 = 8 。
 * 另外,bitmap 的数组大小,使用 {@link #bitmapLength} 来标记。或者说,bitmap 数组,默认按照 Subpage 的大小为 16B 来初始化。
 *    为什么是这样的设定呢?因为 PoolSubpage 可重用,通过 {@link #init(PoolSubpage, int)} 进行重新初始化。
 */
private final long[] bitmap;

/**
 * 双向链表,前一个 PoolSubpage 对象
 */
PoolSubpage<T> prev;
/**
 * 双向链表,后一个 PoolSubpage 对象
 */
PoolSubpage<T> next;

/**
 * 是否未销毁
 */
boolean doNotDestroy;
/**
 * 每个 Subpage 的占用内存大小
 */
int elemSize;
/**
 * 总共 Subpage 的数量
 */
private int maxNumElems;
/**
 * {@link #bitmap} 长度
 */
private int bitmapLength;
/**
 * 下一个可分配 Subpage 的数组位置
 */
private int nextAvail;
/**
 * 剩余可用 Subpage 的数量
 */
private int numAvail;

PoolSubpage有一个PoolSubpage池,第一次申请小内存空间的时候,需要先申请一个空闲页,然后将该页转成PoolSubpage,再将该页设为已被占用,最后再把这个PoolSubpage存到PoolSubpage池中。这样下次就不需要再去申请空闲页了,直接去池中找就好了。Netty中有36种PoolSubpage,所以用36个PoolSubpage链表表示PoolSubpage池。再来看看PoolSubpage怎么分配内存的

long allocate() {
   
    if (elemSize == 0) {
        return toHandle(0);
    }

   
    if (numAvail == 0 || !doNotDestroy) {
        return -1;
    }

    // 获得下一个可用的 Subpage 在 bitmap 中的总体位置
    final int bitmapIdx = getNextAvail();
    // 获得下一个可用的 Subpage 在 bitmap 中数组的位置
    int q = bitmapIdx >>> 6;
    // 获得下一个可用的 Subpage 在 bitmap 中数组的位置的第几 bits
    int r = bitmapIdx & 63;
    assert (bitmap[q] >>> r & 1) == 0;
    // 修改 Subpage 在 bitmap 中不可分配。
    bitmap[q] |= 1L << r;

    // 可用 Subpage 内存块的计数减一
    if (-- numAvail == 0) { // 无可用 Subpage 内存块
        // 从双向链表中移除
        removeFromPool();
    }

    // 计算 handle
    return toHandle(bitmapIdx);
}

PoolSubpage就分析到这里了。

相关文章

网友评论

      本文标题:Netty源码分析(九) PoolSubpage

      本文链接:https://www.haomeiwen.com/subject/prbvxqtx.html