在 Netty 的 PoolChunk 中,分配内存的核心逻辑是通过 allocateNode(int d) 方法实现的,其中 d 表示所需内存块在二叉树中的深度(层级)。以下是针对请求分配大小为 p 的内存块的完整流程和代码解析:


1. 确定所需内存的深度 d

首先需要将请求的内存大小 p 转换为对应的二叉树深度 d

  • 规则:Netty 的 PoolChunk 采用完全二叉树管理内存,每个叶子节点代表一个 8KB 的内存块(默认 chunkSize=16MB,叶子节点数 2048=16MB/8KB)。

  • 计算深度 d

     
    int normCapacity = normalizeSize(p); // 标准化请求大小(对齐到2的幂次)
    int d = maxOrder - (log2(normCapacity / pageSize)); // pageSize=8KB

     

    • 请求 p=8KB → d=11(直接分配叶子节点)

    • 请求 p=16KB → d=10(需分配父节点,合并两个连续的8KB叶子节点)


2. 分配逻辑代码(简化版)

以下是 PoolChunk.allocateNode(int d) 的核心代码流程:

 
long allocateNode(int d) {
    int id = 1; // 从根节点开始查找
    int initial = -(1 << d); // 计算掩码,用于快速跳过不可用分支

    byte val = memoryMap[id]; // 获取当前节点的值
    if (val > d) { // 当前节点无法满足要求
        return -1; // 分配失败
    }

    // 递归查找满足深度d的节点
    while (val < d || (id & initial) == 0) {
        id <<= 1; // 往下走一层,尝试左子节点
        val = memoryMap[id];
        if (val > d) { // 左子节点不满足,尝试右子节点
            id ^= 1; // 切换到右子节点
            val = memoryMap[id];
        }
    }

    byte value = memoryMap[id];
    assert value == d && (id & initial) == 1 << d : String.format("val=%d, d=%d, id=%d", value, d, id);

    memoryMap[id] = maxOrder + 1; // 标记当前节点为已分配
    updateParentsAlloc(id); // 更新父节点的分配状态
    freeBytes -= runLength(id); // 减少剩余可用内存
    return id; // 返回分配到的节点ID
}

3. 辅助方法说明

(1) updateParentsAlloc(int id)

更新父节点的 memoryMap 值,确保其反映子节点的最新状态:

 
private void updateParentsAlloc(int id) {
    while (id > 1) {
        int parentId = id >>> 1;
        byte val1 = memoryMap[id];
        byte val2 = memoryMap[id ^ 1]; // 兄弟节点
        memoryMap[parentId] = (byte) Math.min(val1, val2); // 取子节点的最小值
        id = parentId;
    }
}

(2) runLength(int id)

计算节点 id 对应的内存块大小:

 
private int runLength(int id) {
    return 1 << log2ChunkSize - depth(id); // 2^(log2(16MB) - depth)
}

(3) normalizeSize(int size)

标准化请求大小(对齐到2的幂次):

 
 
private static int normalizeSize(int size) {
    if (size >= chunkSize) return chunkSize;
    return Integer.highestOneBit(size); // 取最接近的2的幂次
}
 
posted on 2025-05-25 12:17  towboat  阅读(10)  评论(0)    收藏  举报