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

news2024/11/24 11:58:30

文章目录

  • 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 DEFAULT_MAX_CAPACITY = Integer.MAX_VALUE;

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…),直到倍增后的结果大于或等于所需的容量值。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Go 简易速速上手小册》第3章:数据结构(2024 最新版)

文章目录 3.1 数组与切片&#xff1a;Go 语言的动态队伍3.1.1 基础知识讲解3.1.2 重点案例&#xff1a;动态成绩单功能描述实现代码扩展功能 3.1.3 拓展案例 1&#xff1a;数据分析功能描述实现代码扩展功能 3.1.4 拓展案例 2&#xff1a;日志过滤器功能描述实现代码扩展功能 3…

LeetCode-第70题-爬楼梯

1.题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 2.样例描述 3.思路描述 画图就可以发现规律&#xff0c;典型的斐波那契额数列 4.代码展示 class Solution {public int climbStair…

最简单的基于 FFmpeg 的封装格式转换器(无编解码)

最简单的基于 FFmpeg 的封装格式转换器&#xff08;无编解码&#xff09; 最简单的基于 FFmpeg 的封装格式转换器&#xff08;无编解码&#xff09;正文结果工程文件下载 最简单的基于 FFmpeg 的封装格式转换器&#xff08;无编解码&#xff09; 参考雷霄骅博士的文章&#xf…

软件工程师,为什么不喜欢关电脑

概述 你是否注意到&#xff0c;软件工程师们似乎从不关电脑&#xff0c;也不喜欢关电脑&#xff1f;别以为他们是电脑“上瘾”&#xff0c;或是沉迷于电脑&#xff0c;这一现象背后蕴含着多种实际原因。 1、代码保存与恢复。 在编写代码过程中&#xff0c;遇到问题时可能会暂时…

Java 基于 SpringBoot+Vue 的酒店管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

C++数据结构与算法——栈与队列

C第二阶段——数据结构和算法&#xff0c;之前学过一点点数据结构&#xff0c;当时是基于Python来学习的&#xff0c;现在基于C查漏补缺&#xff0c;尤其是树的部分。这一部分计划一个月&#xff0c;主要利用代码随想录来学习&#xff0c;刷题使用力扣网站&#xff0c;不定时更…

二维数组及函数的非函数实现

2024年2月14日 1.请编程实现二维数组的杨慧三角 #include<stdio.h> #include<stdlib.h> #include<string.h> void Yanghui(int n,int (*p)[n]) {for(int i0;i<n;i){for(int j0;j<i;j){if(j0||ij){*(*(pi)j)1;}else{*(*(pi)j)*(*(pi-1)j-1)*(*(pi-1)j)…

SpringBoot整合GateWay(详细配置)

前言 在Spring Boot中整合Spring Cloud Gateway是一个常见的需求&#xff0c;尤其是当需要构建一个微服务架构的应用程序时。Spring Cloud Gateway是Spring Cloud生态系统中的一个项目&#xff0c;它提供了一个API网关&#xff0c;用于处理服务之间的请求路由、安全、监控和限流…

Ubuntu20.04 安装jekyll

首先使根据官方文档安装&#xff1a;Jekyll on Ubuntu | Jekyll • Simple, blog-aware, static sites 如果没有报错&#xff0c;就不用再继续看下去了。 我这边在执行gem install jekyll bundler时报错&#xff0c;所以安装了rvm&#xff0c;安装rvm可以参考这篇文章Ubuntu …

【网站项目】155在线考试与学习交流网页平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Ubuntu 20.04 安装RVM

RVM是管理Ruby版本的工具,使用RVM可以在单机上方便地管理多个Ruby版本。 下载安装脚本 首先使下载安装脚本 wget https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer 如果出现了 Connection refused 的情况, 可以考虑执行以下命令修改dns,再执…

2024HVV | 12款开源渗透测试工具(非常详细)零基础入门到精通,收藏这一篇就够了

回顾过去&#xff0c;黑客入侵异常困难&#xff0c;需要大量手动操作。然而&#xff0c;如今&#xff0c;一套自动化测试工具让渗透测试人员变身“半机械人”&#xff0c;能够比以往任何时候都更轻松地完成更多测试。以下12款开源渗透测试工具&#xff0c;可以帮助渗透测试人员…

羊大师发现,奶源对羊奶会产生如此重大的影响

羊大师发现&#xff0c;奶源对羊奶会产生如此重大的影响 羊奶对于人类来说是一种极其营养丰富的食物&#xff0c;日常生活中必不可少。而对于儿童来说&#xff0c;除母乳外&#xff0c;奶粉也是一种非常重要的营养补充品。成人饮用的羊奶对于羊奶的来源和产地要求较低&#xf…

【c++】list详细讲解

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉list库 > 毒鸡汤&#xff1a;你的脸上云淡…

五分钟搭建本地大数据集群

引言 刚接触大数据以及部分接触大数据多年的伙伴可能从来没有自己搭建过一套属于自己的大数据集群&#xff0c;今天就花点时间聊聊怎么快速搭建一套属于自己、且可用于操作、调试的大数据集群 正文 本次搭建的组件都有以下服务以及对应的版本 hadoop&#xff08;3.2.4&…

MySQL运行错误:‘mysql‘不是内部或外部命令,也不是可运行程序或批处理文

主要原因是&#xff1a;没有将mysql安装目录下的bin目录&#xff0c;添加到系统变量中 编辑系统环境变量 双击Path即可 下一步 记得每一步点击确定就好啦。 下面验证一下是否成功呢&#xff1f; 输入命令符(V是大写的哦~&#xff09; mysql -V 以上就是成功啦&#xff01…

【VTKExamples::PolyData】第三十三期 MiscCellData

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例MiscCellData,了解如何创建PolyData数据,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. MiscCellData /…

用Java实现简单的图书管理系统

目录 1.总体框架 2.book包 Books类 booklist类 3.operation包 IO接口&#xff1a; addbooks类&#xff1a; borrowbooks类&#xff1a; delbooks类&#xff1a; returnbooks类&#xff1a; exit类&#xff1a; 4.user包 user类 Adminuser类&#xff08;难点&#…

阅读笔记(BMSB 2018)Video Stitching Based on Optical Flow

参考文献 Xie C, Zhang X, Yang H, et al. Video Stitching Based on Optical Flow[C]//2018 IEEE International Symposium on Broadband Multimedia Systems and Broadcasting (BMSB). IEEE, 2018: 1-5. 摘要 视频拼接在计算机视觉中仍然是一个具有挑战性的问题&#xff0…

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 批量创建分区…