目录

一、 背景简介

二、 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相关推荐

  1. 四十七、Netty零拷贝

    零拷贝的定义 Zero-copy, 就是在操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域. 因为少了一次内存的拷贝, 因此 CPU 的效率就得到的提升. 在 OS 层面上 ...

  2. 80-15-020-原理-零拷贝-Netty零拷贝的原理

    1.概述 Netty 的零拷贝 1. 传统意义的拷贝 是在发送数据的时候,传统的实现方式是: File.read(bytes) Socket.send(bytes) 这种方式需要四次数据拷贝和四次上下 ...

  3. 【Netty】Netty零拷贝原理

    前言 理解零拷贝 零拷贝是Netty的重要特性之一,而究竟什么是零拷贝呢? WIKI中对其有如下定义: "Zero-copy" describes computer operati ...

  4. Netty、Kafka中的零拷贝技术到底有多牛?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:rrd.me/ggFBd 零拷贝,从字面意思理解就是数据不需 ...

  5. 深入探秘 Netty、Kafka 中的零拷贝技术!

    作者:ksfzhaohui 原文:juejin.im/post/5cad6f1ef265da039f0ef5df 零拷贝,从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能.我们也经常在 J ...

  6. 理解Netty中的零拷贝(Zero-Copy)机制

    理解Netty中的零拷贝(Zero-Copy)机制 发表于2年前(2014-01-13 15:11)   阅读(10209) | 评论(12) 164人收藏此文章,我要收藏 赞29 12月12日北京O ...

  7. Netty编解码,粘包拆包及零拷贝

    Netty编解码 Netty涉及到编解码的组件有Channel.ChannelHandler.ChannelPipe等,先大概了解下这几个组件的作用. ChannelHandler ChannelHa ...

  8. 计算机IO系列「一」零拷贝技术

    深入剖析Linux IO原理和几种零拷贝机制的实现 转载自:深入剖析Linux IO原理和几种零拷贝机制的实现 - 知乎 前言 零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将 ...

  9. 深入剖析Linux IO原理和几种零拷贝机制的实现

    本文来说下Linux IO原理和几种零拷贝机制的实现 文章目录 概述 物理内存和虚拟内存 物理内存 虚拟内存 内核空间和用户空间 内核空间 用户空间 Linux的内部层级结构 Linux I/O读写方 ...

最新文章

  1. 腾讯offer是什么样子_记一次腾讯社招前端面试(已拿到offer入职)
  2. 【深入Java虚拟机JVM 06】垃圾收集概述
  3. SpringSecurity案例之把资源交给OAuth2的资源服务管理
  4. 求特殊方程的正整数解
  5. 【接口测试】接口和接口文档概念
  6. 爬取百万github用户数据,查找谁才是python大牛?
  7. ZJYYC LSH去年买了个表(也是LZY去年买了个表) DFS
  8. 大数字加法运算(超过1000位)
  9. 依赖多个项目,重复jar包不同版本冲突解决
  10. 每天一道博弈论之“肥猫的游戏”
  11. 2021 Android APK反编译 apktool使用教程
  12. 面试造火箭,秋招建大楼!阿里新出《Java权威面试指南》堪称精品!
  13. Sql server 去除字段回车换行符
  14. JSP用户登录连接数据库
  15. 关于实现联系人中英文名排序的问题
  16. NodeJS:redis 入门级使用示例 hgetall
  17. 尚硅谷-后台管理系统
  18. 网络精英赛模拟练习(6)
  19. JavaScript(JS) 音乐播放器
  20. java游戏开发——连连看小游戏

热门文章

  1. SpringBoot+Vue打造公司货物订单管理系统
  2. 计算机硬件与软件ppt,计算机硬件和软件.ppt
  3. createjs typescript代码提示
  4. origin自定义函数
  5. 深圳立仪科技进军2021年DME中国(东莞)机械展会
  6. 最大公约数、最小公倍数算法思想
  7. python画二维温度云图_python定制后处理云图
  8. 《计算机网络》day04-计算机网络的功能特性
  9. python 图像等比例缩放
  10. 正面管教之PHP_正面管教家长互助(PHP)体验课1