netty零拷贝之CompositeByteBuf
目录
一、 背景简介
二、 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 indexcheckComponentIndex(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框架更多模块解读相关源码持续更新中,感兴趣的朋友请移步至个人公众号,谢谢支持
netty零拷贝之CompositeByteBuf相关推荐
- 四十七、Netty零拷贝
零拷贝的定义 Zero-copy, 就是在操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域. 因为少了一次内存的拷贝, 因此 CPU 的效率就得到的提升. 在 OS 层面上 ...
- 80-15-020-原理-零拷贝-Netty零拷贝的原理
1.概述 Netty 的零拷贝 1. 传统意义的拷贝 是在发送数据的时候,传统的实现方式是: File.read(bytes) Socket.send(bytes) 这种方式需要四次数据拷贝和四次上下 ...
- 【Netty】Netty零拷贝原理
前言 理解零拷贝 零拷贝是Netty的重要特性之一,而究竟什么是零拷贝呢? WIKI中对其有如下定义: "Zero-copy" describes computer operati ...
- Netty、Kafka中的零拷贝技术到底有多牛?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/ggFBd 零拷贝,从字面意思理解就是数据不需 ...
- 深入探秘 Netty、Kafka 中的零拷贝技术!
作者:ksfzhaohui 原文:juejin.im/post/5cad6f1ef265da039f0ef5df 零拷贝,从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能.我们也经常在 J ...
- 理解Netty中的零拷贝(Zero-Copy)机制
理解Netty中的零拷贝(Zero-Copy)机制 发表于2年前(2014-01-13 15:11) 阅读(10209) | 评论(12) 164人收藏此文章,我要收藏 赞29 12月12日北京O ...
- Netty编解码,粘包拆包及零拷贝
Netty编解码 Netty涉及到编解码的组件有Channel.ChannelHandler.ChannelPipe等,先大概了解下这几个组件的作用. ChannelHandler ChannelHa ...
- 计算机IO系列「一」零拷贝技术
深入剖析Linux IO原理和几种零拷贝机制的实现 转载自:深入剖析Linux IO原理和几种零拷贝机制的实现 - 知乎 前言 零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将 ...
- 深入剖析Linux IO原理和几种零拷贝机制的实现
本文来说下Linux IO原理和几种零拷贝机制的实现 文章目录 概述 物理内存和虚拟内存 物理内存 虚拟内存 内核空间和用户空间 内核空间 用户空间 Linux的内部层级结构 Linux I/O读写方 ...
最新文章
- 腾讯offer是什么样子_记一次腾讯社招前端面试(已拿到offer入职)
- 【深入Java虚拟机JVM 06】垃圾收集概述
- SpringSecurity案例之把资源交给OAuth2的资源服务管理
- 求特殊方程的正整数解
- 【接口测试】接口和接口文档概念
- 爬取百万github用户数据,查找谁才是python大牛?
- ZJYYC LSH去年买了个表(也是LZY去年买了个表) DFS
- 大数字加法运算(超过1000位)
- 依赖多个项目,重复jar包不同版本冲突解决
- 每天一道博弈论之“肥猫的游戏”
- 2021 Android APK反编译 apktool使用教程
- 面试造火箭,秋招建大楼!阿里新出《Java权威面试指南》堪称精品!
- Sql server 去除字段回车换行符
- JSP用户登录连接数据库
- 关于实现联系人中英文名排序的问题
- NodeJS:redis 入门级使用示例 hgetall
- 尚硅谷-后台管理系统
- 网络精英赛模拟练习(6)
- JavaScript(JS) 音乐播放器
- java游戏开发——连连看小游戏