netty零拷贝之CompositeByteBuf

ByteBuf使用详解:ByteBuff组成、扩容、retain、release、零拷贝(slice、duplicate、compositeByteBuf、unpolled)、深拷贝。 ByteBuf是对字节数据的封装。是netty的Server与Client之间通信的数据传输载体(Netty的数据容器),它提供了一个byte数组(byte[])的抽象视图,既解决了JDK API的局限性,又为网络应用程序的开发者提供了更好的API。ByteBuf使用详解:ByteBuff组成、扩容、retain、release、零拷贝(slice、duplicate、compositeByteBuf、unpolled)、深拷贝。 阅读详情

目录

        一、 背景简介

        二、 netty零拷贝


一、背景简介

在TCP网络数据传输过程中,数据包有可能被分割为独立的几个数据包进行发送,对于服务器接收端来说,单个的数据包是没有任何意义的,只有将这些数据包组合到一起,才能接收后解码然后提供给我们的业务层进行处理,而在数据报价进行整合的过程中,零拷贝做的工作就是避免或者减少内存区域中数据的复制次数,进而提高程序的响应性能。

二、 netty零拷贝

netty对于零拷贝有几种不同的形式,其本质上都是讲两个或者多个ByteBuf逻辑上组合到一起,物理上不一定是连续的,在操作数据时候, 不必再将一个ByteBuf拷贝到另一个ByteBuf中去. 因此少了内存的拷贝。而且netty的ByteBuf 支持 slice 操作, 可以将 ByteBuf 分解为多个 ByteBuf, 这些ByteBuf共享同一个内存区域,这样也就避免了内存的拷贝。

CompositeByteBuf 零拷贝:

CompositeByteBuf字面意思就是组合ByteBuf,他会把多个ByteBuf组合到一起,这些ByteBuf在逻辑上连续,实际物理地址不一定连续。

CompositeByteBuf中主要通过addComponent方法进行ByteBuf的合并。

进入到addComponent方法

    public CompositeByteBuf addComponents(boolean increaseWriterIndex, ByteBuf... buffers) {
        addComponents0(increaseWriterIndex, components.size(), buffers, 0, buffers.length);
        consolidateIfNeeded();
        return this;
    }

核心逻辑就是addComponent0方法,consolidateIfNeeded()仅仅是判断合并组件数是否超过当前操作允许的最大值,如果超过最大值,就会进行扩容操作,如下:

    private void consolidateIfNeeded() {
        // 合并组件数是否超过当前操作允许的最大值。
        final int numComponents = components.size();
        if (numComponents > maxNumComponents) {
            final int capacity = components.get(numComponents - 1).endOffset;
​
            ByteBuf consolidated = allocBuffer(capacity);
​
            // 我们没有使用foreach来避免创建迭代器。
            for (int i = 0; i < numComponents; i ++) {
                Component c = components.get(i);
                ByteBuf b = c.buf;
                consolidated.writeBytes(b);
                c.freeIfNecessary();
            }
            Component c = new Component(consolidated);
            c.endOffset = c.length;
            components.clear();
            components.add(c);
        }
    }

其扩容逻辑并不复杂。

继续来到addComponent0方法。

    private int addComponents0(boolean increaseWriterIndex, int cIndex, ByteBuf[] buffers, int offset, int len) {
        checkNotNull(buffers, "buffers");
        int i = offset;
        try {
            // 校验Components index
            checkComponentIndex(cIndex);
            // 无需合并
            while (i < len) {
                // Increment i now to prepare for the next iteration and prevent a duplicate release (addComponent0
                // will release if an exception occurs, and we also release in the finally block here).
                ByteBuf b = buffers[i++];
                if (b == null) {
                    break;
                }
                cIndex = addComponent0(increaseWriterIndex, cIndex, b) + 1;
                int size = components.size();
                if (cIndex > size) {
                    cIndex = size;
                }
            }
            return cIndex;
        } finally {
            for (; i < len; ++i) {
                ByteBuf b = buffers[i];
                if (b != null) {
                    try {
                        b.release();
                    } catch (Throwable ignored) {
                        // 安静的释放ByteBuf
                    }
                }
            }
        }
    }

其核心逻辑就是通过while循环依次遍历每一个ByteBuf然后调用重载方法addComponent0进行添加每一个ByteBuf,最后将每一个ByteBuf进行内存释放。

接着进入重载方法addComponent0看看是如何添加每一个ByteBuf的。

    private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
        assert buffer != null;
        boolean wasAdded = false;
        try {
            checkComponentIndex(cIndex);
​
            int readableBytes = buffer.readableBytes();
​
            // 无需合并-只需将组件添加到列表中.
            @SuppressWarnings("deprecation")
            Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());
            if (cIndex == components.size()) {
                wasAdded = components.add(c);
                if (cIndex == 0) {
                    c.endOffset = readableBytes;
                } else {
                    Component prev = components.get(cIndex - 1);
                    c.offset = prev.endOffset;
                    c.endOffset = c.offset + readableBytes;
                }
            } else {
                components.add(cIndex, c);
                wasAdded = true;
                if (readableBytes != 0) {
                    updateComponentOffsets(cIndex);
                }
            }
            if (increaseWriterIndex) {
                writerIndex(writerIndex() + buffer.readableBytes());
            }
            return cIndex;
        } finally {
            if (!wasAdded) {
                buffer.release();
            }
        }
    }

其核心逻辑不难分析,主要就是添加组件、改变偏移量和end偏移量,如果开启了写索引递增,那么就将写索引加上每个ByteBuf的可读字节,最后如果添加组件失败,就将当前组件ByteBuf进行release释放。

总的来说CompositeByteBuf是通过内部封装的List<Component> components将ByteBuf进行合并,在合并的过程中我们可以手动设置是否递增写索引,进而从逻辑上可以操作多个ByteBuf而不必在物理地址上将其拷贝。

个人才疏学浅、信手涂鸦,netty框架更多模块解读相关源码持续更新中,感兴趣的朋友请移步至个人公众号,谢谢支持😜😜......

公众号:wenyixicodedog

Netty中级进阶:ByteBuf内存模型、零拷贝与私有协议编解码实战 TCP是流式协议,数据没有天然边界,粘包与拆包因此成为所有网络服务端开发者必须直面的基础问题。Netty通过ByteBuf统一管理堆内、堆外和池化内存,以引用计数控制生命周期,并结合零拷贝技术减少数据复制,从而在高并发场景下显著降低GC压力与I/O开销。理解这些底层机制,是真正用好Netty的前提。在实际工程中,无论是设计二进制私有协议、实现LengthFieldBasedFrameDecoder接入,还是排查堆外内存泄漏,都需要围绕ByteBuf和内存模型展开。本文以中级拓展为视角,从内存模型、零拷贝、粘 阅读详情

相关推荐

Netty 零拷贝技术

Netty 实现高性能的另一个高阶特性——零拷贝。零拷贝是一个耳熟能详的词语,在 Linux、Kafka、RocketMQ 等知名的产品中都有使用,通常用于提升 I/O 性能。而且零拷贝也是面试过程中的高频问题,那么你知道零拷贝体现在哪些地方吗?Netty 的零拷贝技术又是如何实现的呢?接下来我们就针对 Netty 零拷贝特性进行详细地分析。 传统 Linux 中的零拷贝技术 在介绍 Netty 零拷贝特性之前,我们有必要学习下传统 Linux 中零拷贝的工作原理。所谓零拷贝,就是在数据操作时,不需要将数据

748

Netty零拷贝之CompositeByteBuf实际用法

Netty所谓的零拷贝就是在数据序列化操作的时候,尽量减少数据的复制。比如将一个byte[]转化为ByteBuf,如果这样写,就会多一次数据的复制: String a = "ccc"; byte[] bytesSrc = a.getBytes(CharsetUtil.UTF_8); ByteBuf byteBuf = Unpooled.buffer(...

王广帅--游戏开发-服务器开发 4752

PostgreSQL+Citus分布式集群实战:从零搭建到性能调优

本文详细介绍了如何从零开始搭建并优化PostgreSQL+Citus分布式数据库集群。内容涵盖集群规划、源码编译安装、Citus扩展部署、节点配置、分布式表创建以及核心性能调优策略,为应对海量数据增长提供了完整的部署指南和实战解决方案。

oo7890的博客 627

Netty数据容器ByteBuf详解

网络数据的基本单位总是字节。Java NIO 提供了ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐。 ​ Netty 的ByteBuffer 替代品是ByteBuf,一个强大的实现,既解决了JDK API 的局限性,又为网络应用程序的开发者提供了更好的API。

学海无涯,行者无疆 1524

避坑指南:中国地面气候日值数据集(V3.0)处理中的常见错误与解决方案

本文详细解析了中国地面气候日值数据集(V3.0)处理中的常见错误与解决方案,包括数据清洗、特征值解码、时间序列处理和质量控制等关键步骤。通过Python实战代码示例,帮助研究者高效处理这一包含全国699个气象站多要素日值数据的数据集,避免常见陷阱,提升气候变化研究和农业气象分析的准确性。

xray4的博客 1026

vasp计算练习1-Si

si的vasp训练流程

qq_41074165的博客 3296

吃透Netty源码系列三十五之CompositeByteBuf详解一

吃透Netty源码系列三十五之CompositeByteBuf详解CompositeByteBuf内部结构Component构造方法主要方法CompositeByteBuf重要属性CompositeByteBuf构造方法addComponent(ByteBuf buffer)addComponent0 CompositeByteBuf 简单来说就是各种缓冲区的组合,就是把他们封装到一个缓冲区,或者...

王伟王胖胖的博客 2619

RK3568/RK3588之修改8250驱动实现RS485收发的自动切换

在串口发送前,若为485,则将控制引脚拉为发送状态,在发送后,循环查看是否发送完成,若发送完成则将引脚置回读状态,如此一来,就能实现在内核测控制方向切换,而不会因为延时造成数据丢失,经过测试此办法可行。全部修改完成后,重新编译生成内核文件和设备树文件,烧写到板子上即可。

哒宰的博客 3114

Netty 揭秘CompositeByteBuf:零拷贝优化核心技术

CompositeByteBuf是Netty中实现虚拟缓冲区的核心类,通过将多个ByteBuf合并为单一逻辑视图来减少数据复制。其核心设计包括: 零拷贝优化:通过组合而非复制提升性能,保持底层数据物理隔离 分层索引系统:维护逻辑索引到物理索引的三层映射 关键实现包括: 使用Component内部类封装每个缓冲区的元数据 通过二分查找+缓存优化索引定位 提供consolidate()进行组件合并优化 支持discardReadBytes()等细粒度内存回收

lifallen的博客 1202

时钟门控ICG单元的timing问题

本文探讨了数字IC设计中门控时钟(ICG)的时序收敛问题,重点分析了ICG单元在setup时序检查中易出现违例的原因及优化方法。文章指出,由于ICG单元不在时钟树平衡范围内,其时钟路径延迟通常小于后续寄存器,导致setup时序难以满足。提出的解决方案包括:1)将ICG尽量靠近受控寄存器放置;2)使用set_clock_gating_check命令加强时序约束;3)在布局阶段设置负时钟延迟;4)CTS阶段设置插入延迟。同时强调set_clock_gating_check命令对ICG单元同样有效,并介绍了ICG

u011075954的专栏 1106

YOLO + SubspaceAD:一张良品图,检出所有未知缺陷

当YOLO遇上子空间建模,工业质检正迎来从“见多识广”到“举一反三”的质变时刻。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 495

netty 校验_netty零拷贝之CompositeByteBuf

目录一、 背景简介二、netty零拷贝一、背景简介在TCP网络数据传输过程中,数据包有可能被分割为独立的几个数据包进行发送,对于服务器接收端来说,单个的数据包是没有任何意义的,只有将这些数据包组合到一起,才能接收后解码然后提供给我们的业务层进行处理,而在数据报价进行整合的过程中,零拷贝做的工作就是避免或者减少内存区域中数据的复制次数,进而提高程序的响应性...

weixin_39955700的博客 139

PINN疲劳寿命预测优化

本项目基于物理信息神经网络(PINN)构建材料疲劳寿命预测模型,通过融合Paris裂纹扩展方程与实验数据,实现裂纹扩展行为的精准预测。核心方法包括:1)将Paris方程作为物理约束嵌入神经网络训练;2)生成含噪声的模拟数据并进行归一化处理;3)采用PINN-GA联合优化框架,以裂纹扩展速率最小化为目标优化材料参数。该方案通过物理规律与数据驱动的结合,显著提升预测模型的泛化能力,为工程材料寿命评估提供新思路。

huanghm88的专栏 146

深入解析Netty零拷贝技术:FileRegion的transferTo与CompositeByteBuf的虚拟缓冲聚合

在网络编程领域,数据拷贝一直是制约性能的关键瓶颈。传统的数据传输流程中,数据需要经历多次拷贝:从内核缓冲区到用户空间缓冲区,再从用户空间缓冲区到网络协议栈。这种冗余的数据移动不仅消耗CPU资源,还增加了内存带宽压力,导致显著的性能损耗。零拷贝技术正是为解决这一问题而生的革命性方案,它通过消除不必要的数据拷贝操作,实现数据在系统各组件间的直接传输。

zuiyuelong的博客 847

EDEM-fluent耦合时出现的问题及摸索出的解决办法及DPM颗粒信息导出

EDEM-fluent耦合时出现的问题及摸索出的解决办法及DPM颗粒信息导出

zheaa的博客 5749

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Netty ByteBuf 与零拷贝:CompositeByteBuf 与 FileChannel.transferTo

基于源码深度解析,Netty ByteBuf 与零拷贝:CompositeByteBuf 与 FileChannel.transferTo

m0_57877510的博客 430

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

AI 模拟面试实战:Netty 零拷贝(Zero-Copy)底层机制:ByteBuf 内存切片、CompositeByteBuf 与 Linux sendfile 源码级拆解

在 Java 高性能网络编程、RPC 通信框架(gRPC、Dubbo)以及分布式存储(Kafka、RocketMQ)面试中,是技术专家面试官用来检验候选人是否具备“操作系统内核态/用户态边界感知力与高性能 I/O 穿透力”的殿堂级考点。很多初学者在背八股文时,往往把“操作系统底层的零拷贝”与“Netty 框架层面的零拷贝”混为一谈,答题语焉不详。但当大厂技术总监在白板上画出 Linux 内核页缓存与用户态内存布局,深入追问:sendfile()mmap()Netty 的、以及堆外直接内存(

cannonjinx的博客 1959

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

netty Slice 零拷贝 和 CompositeByteBuf

@Slf4j public class TestSlice { public static void main(String[] args) { ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(10); byteBuf.writeBytes(new byte[]{'a','b','c','d','e','f','g','h','i','j'}); byte[] bytes = new byte[10]

weixin_43978420的博客 475

Netty中的零拷贝

一.零拷贝的定义 Zero-copy, 就是在操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域. 因为少了一次内存的拷贝, 因此 CPU 的效率就得到的提升. 在 OS 层面上的 Zero-copy 通常指避免在 用户态(User-space) 与 内核态(Kernel-space) 之间来回拷贝数据。 但Netty 中的 Ze...

SmallCatBaby的博客 2941

Netty零拷贝

Netty零拷贝

Deronn的博客 1466

Netty实现的零拷贝:原理、源码与实践

摘要: Netty通过零拷贝技术优化数据传输效率,减少CPU和内存开销。其实现分为操作系统层面和用户空间层面:1)操作系统层面利用sendfile机制,通过FileRegion和transferTo直接传输文件数据,避免用户空间拷贝,支持SG-DMA时实现完全零拷贝;2)用户空间层面通过CompositeByteBuf虚拟聚合多个ByteBuf,逻辑连续访问并零拷贝写入网络,减少内存复制。两种方式分别针对大文件传输和多段数据聚合场景,显著降低CPU占用、内存带宽压力及传输延迟,适用于高并发和低延迟应用。

持续输出Java相关知识 1018

Netty ByteBuf 的零拷贝(Zero Copy)详解

Netty ByteBuf 的零拷贝(Zero Copy)详解

深圳市多克创新科技有限公司 1578

彻底搞懂Netty高性能之零拷贝

作为Java网络编程学习者,不仅要知道NIO,还一定要学习Mina和Netty这两个优秀的网络框架。作为上一篇NIO效率高的原理之零拷贝与直接内存映射的补充,本文将针对Netty的零拷贝特性进行详细分析。 Netty高性能的原因 Netty作为异步事件驱动的网络框架,高性能主要来自于其I/O模型和线程处理模型,前者决定如何收发数据,后者决定如何处理数据。 Netty高性能的原因总结,智者见智...

全菜工程师小辉的博客 5730
上一篇: netty ByteOrder大小端
下一篇: netty writeAndFlush源码分析
wenyixicodedog
博客等级 码龄8年 87粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值