这篇文章主要为大家展示了“Netty分布式ByteBuf如何使用page级别的内存分配”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Netty分布式ByteBuf如何使用page级别的内存分配”这篇文章吧。之前我们介绍过, netty内存分配的单位是chunk, 一个chunk的大小是16MB, 实际上每个chunk, 都以双向链表的形式保存在一个chunkList中, 而多个chunkList, 同样也是双向链表进行关联的, 大概结构如下所示:在chunkList中, 是根据chunk的内存使用率归到一个chunkList中, 这样, 在内存分配时, 会根据百分比找到相应的chunkList, 在chunkList中选择一个chunk进行内存分配这里总共定义了6个chunkList, 并在构造方法将其进行初始化跟到其构造方法中:首先通过new PoolChunkList()这种方式将每个chunkList进行创建, 我们以q050 =newPoolChunkList
这里主要拆解了如下步骤1. 在原有的chunk中进行分配2. 创建chunk进行分配3. 初始化ByteBuf首先我们看第一步, 在原有的chunk中进行分配:我们之前讲过, chunkList是存储不同内存使用量的chunk集合, 每个chunkList通过双向链表的形式进行关联, 这里的q050.allocate(buf, reqCapacity, normCapacity)就代表首先在q050这个chunkList上进行内存分配我们以q050为例进行分析, 跟到q050.allocate(buf, reqCapacity, normCapacity)方法中:longhandle = cur.allocate(normCapacity)表示对于每个chunk, 都尝试去分配if(handle
如果handle大于0说明已经分配到了内存, 则通过cur.initBuf(buf, handle, reqCapacity)对byteBuf进行初始化if(cur.usage() >= maxUsage)代表当前chunk的内存使用率大于其最大使用率, 则通过remove(cur)从当前的chunkList中移除, 再通过nextList.add(cur)添加到下一个chunkList中我们再回到PoolArena的allocateNormal方法中:我们看第二步PoolChunk
和depthMap =newbyte[memoryMap.length]这两步首先看memoryMap =newbyte[maxSubpageAllocs
这里初始化了一个字节数组memoryMap, 大小为maxSubpageAllocs
depthMap =newbyte[memoryMap.length]同样也是初始化了一个字节数组, 大小为memoryMap的大小, 也就是4096继续往下分析之前, 我们看chunk的一个层级关系这是一个二叉树的结构, 左侧的数字代表层级, 右侧代表一块连续的内存, 每个父节点下又拆分成多个子节点, 最顶层表示的内存范围为0-16MB, 其又下分为两层, 范围为0-8MB, 8-16MB, 以此类推, 最后到11层, 以8k的大小划分, 也就是一个page的大小如果我们分配一个8mb的缓冲区, 则会将第二层的第一个节点, 也就是0-8这个连续的内存进行分配, 分配完成之后, 会将这个节点设置为不可用, 具体逻辑后面会讲解结合上面的图, 我们再看构造方法中的for循环:实际上这个for循环就是将上面的结构包装成一个字节数组memoryMap, 外层循环用于控制层数, 内层循环用于控制里面每层的节点, 这里经过循环之后, memoryMap和depthMap内容为以下表现形式:[0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4………..]这里注意一下, 因为程序中数组的下标是从1开始设置的, 所以第零个节点元素为默认值0这里数字代表层级, 同时也代表了当前层级的节点, 相同的数字个数就是这一层级的节点数其中0为2个(因为这里分配时下标是从1开始的, 所以第0个位置是默认值0, 实际上第零层元素只有一个, 就是头结点), 1为2个, 2为4个, 3为8个, 4为16个, n为2的n次方个, 直到11, 也就是11有2的11次方个我们继续剖析longhandle = c.allocate(normCapacity)这步如果分配是以page为单位, 则走到allocateRun(normCapacity)方法中, 跟进去:intd = maxOrder – (log2(normCapacity) – pageShifts)表示根据normCapacity计算出图5-8-5中的第几层intid = allocateNode(d)表示根据层级关系, 去分配一个节点, 其中id代表memoryMap中的下标这里是实际上是从第一个节点往下找, 找到层级为d未被使用的节点, 我们可以通过注释体会其逻辑找到相关节点后通过setValue将当前节点设置为不可用, 其中id是当前节点的下标, unusable代表一个不可用的值, 这里是12, 因为我们的层级只有12层, 所以设置为12之后就相当于标记不可用设置成不可用之后, 通过updateParentsAlloc(id)逐层设置为被使用
本文小编为大家详细介绍“Java中的函数式编程怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java中的函数式编程怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。函数式编程的理论基础是阿隆佐丘奇(Alonzo Chu…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。