Netty Review - ByteBuf扩容机制源码解析

文章目录

  • Pre
  • 概述
  • 前置知识: 名词解释
  • writeByte 源码解析
    • 实现
      • ensureWritable0(minWritableBytes)
        • ensureWritable0
          • alloc().calculateNewCapacity
  • 总结

在这里插入图片描述

在这里插入图片描述


Pre

Netty Review - 直接内存的应用及源码分析

Netty Review - 底层零拷贝源码解析

Netty Review - ByteBuf内存池源码解析


概述

ByteBuf 扩容机制是指在写入数据时,如果当前容量不足以容纳新增的数据,则需要进行动态扩容,以适应数据量的增长。

下面是ByteBuf 扩容机制的详细阐述:

  1. 容量检查
    在写入数据之前,会先检查当前可写入的容量是否足够。这通常是通过比较写索引和容量之间的关系来实现的。如果当前可写入容量不足,就需要进行扩容操作。

  2. 内存分配
    当需要扩容时,会分配一个更大的内存空间来存储数据。这个内存空间的大小通常由扩容策略决定,可以是固定大小的增量,也可以是根据某种规则动态计算的。

  3. 数据迁移
    在分配更大的内存空间后,原有的数据需要从旧的内存空间复制到新的内存空间中。这个过程涉及数据的复制和移动,但通常只涉及到已经写入的部分数据,而未写入的部分则不需要迁移。

  4. 索引更新
    扩容完成后,需要更新读写索引和容量信息,以反映新的内存空间状态。通常会更新写索引以指向新的可写入位置,同时更新容量信息以反映新的内存空间大小。

  5. 内存释放
    如果是使用池化的方式分配内存,则在数据迁移完成后,原有的内存空间可能会被释放回内存池中,以便其他 ByteBuf 实例重复利用。

总的来说,ByteBuf 的扩容机制主要包括容量检查、内存分配、数据迁移、索引更新和内存释放等步骤。这个机制确保了 ByteBuf 在写入数据时能够动态地适应数据量的变化,从而保证了其灵活性和高效性。


前置知识: 名词解释

  • minNewCapacity:表用户需要写入的值大小
  • threshold:阈值,为Bytebuf内部设定容量的最大值
  • maxCapacity:Netty最大能接受的容量大小,一般为int的最大值

在这里插入图片描述


writeByte 源码解析

在这里插入图片描述

这段代码是 ByteBuf 接口中的一个方法声明,表示向缓冲区中写入一个字节,并将写入位置的索引增加 1。

/**
 * 向当前 {@code writerIndex} 处设置指定的字节,并将 {@code writerIndex} 在缓冲区中增加 {@code 1}。
 * 指定值的高 24 位将被忽略。
 * 如果 {@code this.writableBytes} 小于 {@code 1},则将调用 {@link #ensureWritable(int)},
 * 尝试扩展容量以容纳。
 */
public abstract ByteBuf writeByte(int value);

这个方法用于向缓冲区中写入一个字节,参数 value 表示要写入的字节值。如果当前可写入的字节数小于 1(即缓冲区容量不足以容纳新的字节),则会调用 ensureWritable(int) 方法来尝试扩展缓冲区的容量,以确保能够容纳新的字节。


实现

在这里插入图片描述

ensureWritable0(minWritableBytes)

实现了 ByteBuf 接口中的 writeByte 方法,用于向缓冲区中写入一个字节。

@Override
public ByteBuf writeByte(int value) {
    // 确保缓冲区有足够的可写空间
    ensureWritable0(1);
    // 将字节写入当前写入位置,并将写入位置后移一位
    _setByte(writerIndex++, value);
    return this;
}

该方法首先调用 ensureWritable0 方法确保缓冲区有足够的可写空间来容纳一个字节。然后调用 _setByte 方法将指定的字节值写入当前的写入位置,并将写入位置向后移动一个字节的长度。最后返回当前 ByteBuf 实例,以支持链式调用。


ensureWritable0

这段代码实现了 ensureWritable0 方法,用于确保缓冲区有足够的可写空间来容纳指定的字节数。以下是对代码的理解和注释:

final void ensureWritable0(int minWritableBytes) {
    // 确保缓冲区是可访问的(未被释放)
    ensureAccessible();
    // 如果可写字节数大于等于要求的最小可写字节数,则无需扩容,直接返回
    if (minWritableBytes <= writableBytes()) {
        return;
    }
    // 检查是否超出最大容量限制
    if (checkBounds) {
        if (minWritableBytes > maxCapacity - writerIndex) {
            throw new IndexOutOfBoundsException(String.format(
                    "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
                    writerIndex, minWritableBytes, maxCapacity, this));
        }
    }

    // 将当前容量规范化为2的幂次方,以便进行内存分配
    int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

    // 调整缓冲区容量为新的容量
    capacity(newCapacity);
}

该方法首先确保缓冲区是可访问的,即未被释放。然后检查当前可写字节数是否满足需求,如果不满足,则计算需要扩容的容量。如果启用了边界检查(checkBounds),还会检查是否超出了最大容量限制。最后,根据计算得到的新容量,调用 capacity 方法进行容量调整。


alloc().calculateNewCapacity

这段代码实现了 calculateNewCapacity 方法,用于计算缓冲区扩容时的新容量。


 static final int CALCULATE_THRESHOLD = 1048576 * 4; // 4 MiB page


@Override
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
    // 检查最小新容量是否为正数或零
    checkPositiveOrZero(minNewCapacity, "minNewCapacity");
    // 如果最小新容量大于最大容量,则抛出异常
    if (minNewCapacity > maxCapacity) {
        throw new IllegalArgumentException(String.format(
                "minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
                minNewCapacity, maxCapacity));
    }
    // 计算阈值,即4 MiB页面大小
    final int threshold = CALCULATE_THRESHOLD; // 4 MiB page

    // 如果最小新容量等于阈值,则返回阈值
    if (minNewCapacity == threshold) {
        return threshold;
    }
		
    f//  采用步进4MB的方式完成扩容
    // 如果超过阈值,则不是按照两倍增长,而是按照阈值增长
    if (minNewCapacity > threshold) {
        int newCapacity = minNewCapacity / threshold * threshold;
        if (newCapacity > maxCapacity - threshold) {
            newCapacity = maxCapacity;
        } else {
            newCapacity += threshold;
        }
        return newCapacity;
    }
	
	// 采用64为基数,做倍增的方式完成扩容	

    // 如果未超过阈值,则按照两倍增长,直到大于等于最小新容量或者达到最大容量
    int newCapacity = 64;
    while (newCapacity < minNewCapacity) {
        newCapacity <<= 1;
    }

    return Math.min(newCapacity, maxCapacity);
}

该方法首先检查最小新容量是否为正数或零,并确保不大于最大容量。然后根据阈值进行不同的扩容策略:

  • 如果最小新容量超过了阈值,则不是按照两倍增长,而是按照阈值增长;
  • 如果未超过阈值,则按照两倍增长,直到大于等于最小新容量或者达到最大容量。
  • 最后返回计算得到的新容量。

总结

Netty的ByteBuf需要动态扩容来满足需要, 这种动态扩容机制通过阈值来判断采用不同的扩容策略:

  1. 如果需要的容量等于门限阈值,则直接使用阈值作为新的缓存区容量。
  2. 如果需要的容量大于阈值,则采用每次步进4MB的方式进行内存扩张,即将需要扩容值除以4MB后乘以4MB,然后将结果与最大容量进行比较,取其中的较小值作为目标容量。
  3. 如果需要的容量小于阈值,则采用倍增的方式,以64字节作为基本数值,每次翻倍增长(如64,128,256…),直到倍增后的结果大于或等于所需的容量值。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/391317.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python - OSError:错误没有名为 [‘pytorch_model.bin‘

python - OSError&#xff1a;错误没有名为 [‘pytorch_model.bin’] 自己训练的模型存储好了以后 model MT5ForConditionalGeneration.from_pretrained(“ner/best”) 之前还可以跑 现在报错 错误没有名为 [‘pytorch_model.bin’] 还原了一下conda env 把四版变成三版了 …

人工智能学习与实训笔记(十五):Scikit-learn库的基础与使用

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 一、介绍 1. 1 Scikit-learn的发展历程及定义 1.2 理解算法包、算法库及算法框架之间的区别和联系 二、Scikit-learn官网结构 三、安装与设置 3.1 Python环境的安装与配置 3.2 Scikit-lea…

【精选】Java面向对象进阶——接口细节:成员特点和接口的各种关系

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

1.逆向基础

文章目录 一、前言二、什么是逆向&#xff1f;三、软件逆向四、逆向分析技术五、文本字符六、Windows系统1.Win API2.WOW643.Windows消息机制4.虚拟内存 一、前言 原文以及后续文章可点击查看&#xff1a;逆向基础 逆向真的是一个很宏大的话题&#xff0c;而且大多数都是相当…

从代码的层面掌握LLM的路线

原则&#xff1a;从易到难&#xff0c;只用 pytorch 从第一个项目来熟悉 transformer 的使用&#xff1b; 从第二个项目来掌握对训练数据的使用方法及 transformer 的 decoder 的细节&#xff1b; 从第三个项目来理解 LLM 的整个过程&#xff1b; 1&#xff0c;Transformer t…

2024/2/17 图论 最短路入门 dijkstra 1

目录 算法思路 Dijkstra求最短路 AcWing 849. Dijkstra求最短路 I - AcWing 850. Dijkstra求最短路 II - AcWing题库 最短路 最短路 - HDU 2544 - Virtual Judge (vjudge.net) 【模板】单源最短路径&#xff08;弱化版&#xff09; P3371 【模板】单源最短路径&#xf…

echarts制作两个柱状图

let colorList[#02ce8b,#ffbe62,#f17373]; let data1 [90,80,70,50] option { title:[{ // 第一个标题text: 环保检测, // 主标题textStyle: { // 主标题样式color: #333,fontWeight: bold,fontSize: 16},left: 20%, // 定位到适合的位置top: 10%, // 定位到适合的位置},{ //…

【plt.scatter绘制散点图】:从入门到精通,只需一篇文章!【Matplotlib】

【plt.scatter绘制散点图】&#xff1a;从入门到精通&#xff0c;只需一篇文章&#xff01;【Matplotlib】&#xff01;&#x1f680; 利用Matplotlib进行数据可视化示例 &#x1f335;文章目录&#x1f335; 一、plt.scatter入门&#xff1a;轻松迈出第一步 &#x1f463;二、…

各类电纸书使用体验

对移动阅读一直有着强烈的愿望&#xff0c;想要一个易于携带&#xff0c;又能看着比较大气的电子阅读器&#xff0c;这是一个矛盾...所以现在用着海信Hi Reader Pro&#xff0c;还想再寻找一个合适的家用阅读器&#xff0c;对自己用过的阅读器总结一下&#xff0c;给大家做个参…

图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化

图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 卷积神经网络的一些基本概念&#xff1a;图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 1.图像卷积、步长、填充 图像卷积&#xff1a;卷积核矩阵在一个原始图像矩阵上 “从上往下、…

XUbuntu22.04之apt与snap如何重装软件(二百一十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Vue2学习第二天

Vue2 学习第二天 1. 数据绑定 Vue 中有 2 种数据绑定的方式&#xff1a; 单向绑定(v-bind)&#xff1a;数据只能从 data 流向页面。双向绑定(v-model)&#xff1a;数据不仅能从 data 流向页面&#xff0c;还可以从页面流向 data。 备注&#xff1a; 双向绑定一般都应用在表单…

比特币 P2PKH、P2SH

标准脚本P2PKH、P2SH 区块链重要基础知识7-1——标准脚本P2PKH、P2SH-CSDN博客 比特币中P2SH(pay-to-script-hash)多重签名的锁定脚本和解锁脚本 https://www.cnblogs.com/itlgl/p/10419325.html

Python算法题集_将有序数组转换为二叉搜索树

Python算法题集_将有序数组转换为二叉搜索树 题108&#xff1a;将有序数组转换为二叉搜索树1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【极简代码递归】2) 改进版一【多行代码递归】3) 改进版二【极简代码递归传递下标】 4. 最优算法 本文为…

StarRocks表设计——分区分桶与副本数

目录 一、数据分布 1.1 概述 1.2 数据分布方式 1.2.1 Round-Robin 1.2.2 Range 1.2.3 List 1.2.4 Hash 1.3 StarRocks的数据分布方式 1.3.1 不分区 Hash分桶 1.3.2 Range分区Hash分桶 三、分区 3.1 分区概述 3.2 创建分区 3.2.1 手动创建分区 3.2.2 批量创建分区…

Stable Diffusion系列(五):原理剖析——从文字到图片的神奇魔法(扩散篇)

文章目录 DDPM论文整体原理前向扩散过程反向扩散过程模型训练过程模型生成过程概率分布视角参数模型设置论文结果分析 要想完成SD中从文字到图片的操作&#xff0c;必须要做到两步&#xff0c;第一步是理解文字输入包含的语义&#xff0c;第二步是利用语义引导图片的生成。下面…

String讲解

文章目录 String类的重要性常用的方法常用的构造方法String类的比较字符串的查找转化数字转化为字符串字符串转数字 字符串替换字符串的不可变性 字符串拆分字符串截取字符串修改 StringBuilder和StringBuffer String类的重要性 在c/c的学习中我们接触到了字符串&#xff0c;但…

阿里(淘天)一面笔试算法原题

阿里撤资 "车来了" 近日&#xff0c;国内实时公交产品"车来了"关联公司武汉元光科技有限公司发生工商变更&#xff0c;阿里巴巴&#xff08;中国&#xff09;网络技术有限公司退出股东行列。 这很好理解&#xff0c;符合近期阿里收缩战线的行为一致性。 毕…

自然语言编程系列(四):GPT-4对编程开发的支持

在编程开发领域&#xff0c;GPT-4凭借其强大的自然语言理解和代码生成能力&#xff0c;能够深刻理解开发者的意图&#xff0c;并基于这些需求提供精准的编程指导和解决方案。对于开发者来说&#xff0c;GPT-4能够在代码片段生成、算法思路设计、模块构建和原型实现等方面给予开…

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(2)项目开发周期

我们来学习项目开发的周期。 再次声明&#xff0c;本文来自腾讯AI课的学习笔记&#xff0c;图片和文字&#xff0c;仅用于大家学习&#xff0c;想了解更多知识&#xff0c;请访问腾讯云相关章节。如果争议&#xff0c;请联系作者。 今天&#xff0c;我们来学习AI项目的周期。 主…