Netty 4.x – ByteBuf

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1、ByteBuf与Java NIO Buffer

ByteBuf则是Java NIO Buffer的新轮子,官方列出了一些ByteBuf的特性:

  • 需要的话,可以自定义buffer类型;
  • 通过组合buffer类型,可实现透明的zero-copy;
  • 提供动态的buffer类型,如StringBuffer一样,容量是按需扩展;
  • 无需调用flip()方法;
  • 常常「often」比ByteBuffer快。

 

2、ByteBuf实现类

ByteBuf提供了一些较为丰富的实现类,逻辑上主要分为两种:HeapByteBuf和DirectByteBuf,实现机制则分为两种:PooledByteBuf和UnpooledByteBuf,除了这些之外,Netty还实现了一些衍生ByteBuf(DerivedByteBuf),如:ReadOnlyByteBuf、DuplicatedByteBuf以及SlicedByteBuf。

ByteBuf实现类的类图如下:

104518_MSlt_3101476.png

HeapByteBuf和DirectByteBuf区别在于Buffer的管理方式:HeapByteBuf由Heap管理,Heap是Java堆的意思,内部实现直接采用byte[] array;DirectByteBuf使用是堆外内存,Direct应是采用Direct I/O之意,内部实现使用java.nio.DirectByteBuffoer。

PooledByteBuf和UnpooledByteBuf,UnpooledByteBuf实现就是普通的ByteBuf了,PooledByteBuf是4.x之后的新特性,稍后再说。

DerivedByteBuf是ByteBuf衍生类,实现采用装饰器模式对原有的ByteBuf进行了一些封装。ReadOnlyByteBuf是某个ByteBuf的只读引用;DuplicatedByteBuf是某个ByteBuf对象的引用;SlicedByteBuf是某个ByteBuf的部分内容。

SwappedByteBuf和CompositedByteBuf我觉得也算某种程度的衍生类吧,SwappedByteBuf封装了一个ByteBuf对象和ByteOrder对象,实现某个ByteBuf对象序列的逆转;CompositedByteBuf内部实现了一个ByteBuf列表,称之为组合ByteBuf,由于不懂相关的技术业务,无法理解该类的存在意义(官方解释:A user can save bulk memory copy operations using a composite buffer at the cost of relatively expensive random access.)。这两个类从逻辑上似乎完全可以继承于DerivedByteBuf,Trustin大神为啥如此设计呢?

3、简要的ByteBuf的实现机制

104604_4oep_3101476.png

ByteBuf有两个指针,readerIndex和writerIndex,用以控制buffer数组的读写。读逻辑较为简单,不考虑边界的情况下,就是`return array[readerIndex++];`。这里简要分析一下HeapByteBuf的读逻辑。

1. AbstractByteBuf.ensureWritable(minWritableBytes);

2. calculateNewCapacity(writerIndex + minWritableBytes)

> 2.1 判断是否超过可写入容量 maxCapacity – writerIndex

> 2.2 超过则抛异常,否则计算新容量 writerIndex + minWritableBytes

> 2.3 判断是否超过设定阈值(4MB),超过每次增加按阈值(4MB)递增,否则

> 2.4 初始大小为64字节(newCapacity),新容量超过newCapacity则翻倍,直到newCapacity大于新容量为止

> 2.5 返回Min(newCapacity, maxCapacity);

3. UnpooledHeapByteBuf.capacity(newCapacity);

> 3.1 确保可访问,有一个`引用计数`的机制,引用计数为0,则抛异常(ensureAccessible)

> 3.2 常规操作:判断是否越界

> 3.3 如果newCapacity比原容量大,则直接创建新数组,并设置。否则

> 3.4 如果readerIndex小于新容量,将readable bytes拷贝至新的数组,反之将readerIndex和writerIndex均设置为newCapacity。

4. setByte(writerIndex++, value)

> 4.1 确保可访问

> 4.2 设置

5、ByteBuf特殊机制

5.1 Pooled

4.x开发了Pooled Buffer,实现了一个高性能的buffer池,分配策略则是结合了buddy allocation和slab allocation的jemalloc变种,代码在io.netty.buffer.PoolArena。暂未深入研读。

官方说提供了以下优势:

  • 频繁分配、释放buffer时减少了GC压力;
  • 在初始化新buffer时减少内存带宽消耗(初始化时不可避免的要给buffer数组赋初始值);
  • 及时的释放direct buffer。

当然,官方也说了不保证没有内存泄露,所以默认情况下还是采用的UnpooledByteBufAllocator。5.x还处于beta版,看它的「 new and noteworthy 」文档也没说有啥变化,哈哈哈哈,查看最新的「 new and noteworthy 」文档,PooledByteBufAllocator已经设置为默认的Allocator (revised in 2014-01-16)。

5.2 Reference Count

ByteBuf的生命周期管理引入了Reference Count的机制,感觉让我回到了CPP时代。可以通过简单的继承SimpleChannelInboundHandler实现自动释放reference count。SimpleChannelInboundHandler的事件方法如下,在消费完毕msg后,可以AutoRelease之:

 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {boolean release = true;try {if (acceptInboundMessage(msg)) {@SuppressWarnings("unchecked")I imsg = (I) msg;messageReceived(ctx, imsg);} else {release = false;ctx.fireChannelRead(msg);}} finally {if (autoRelease && release) {ReferenceCountUtil.release(msg);}}}

这一小节可以单独拎出来和Pooled放在一起深入研读研读,有兴趣的可以先看看官方文档: Reference counted objects

5.3 Zero Copy

Zero-copy与传统意义的 zero-copy 不太一样。传统的zero-copy是IO传输过程中,数据无需中内核态到用户态、用户态到内核态的数据拷贝,减少拷贝次数。而Netty的zero-copy则是完全在用户态,或者说传输层的zero-copy机制,可以参考下图。由于协议传输过程中,通常会有拆包、合并包的过程,一般的做法就是System.arrayCopy了,但是Netty通过ByteBuf.slice以及Unpooled.wrappedBuffer等方法拆分、合并Buffer无需拷贝数据。

如何实现zero-copy的呢。slice实现就是创建一个SlicedByteBuf对象,将this对象,以及相应的数据指针传入即可,wrappedBuffer实现机制类似。

104700_cvvh_3101476.png

 

 

 

 

 

转载于:https://my.oschina.net/LucasZhu/blog/1799162

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

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

相关文章

智能路由器-OpenWRT 系列四 (挂载移动设备)

每次ssh登陆OpenWRT安装新软件时,都必须更新opkg opkg update安装驱动 为了可以识别U盘/移动硬盘,必须安装相关的驱动。 一类是usb相关的驱动 opkg install kmod-usb-core #usb驱动 opkg install kmod-scsi-core #SCSI总线驱动 opkg install kmod-scs…

windows系统vscode检查更新菜单消失且不能自动更新(1.70.0不能自动更新到1.70.2

翻了半天vscode的issues中终于找到了https://github.com/microsoft/vscode/issues/157624 解决方案 不能用管理员身份运行vscode,不然就没有检查更新菜单,关闭后重启vscode就有更新菜单了 相关回答 翻译一下,就是vscode分用户类型和系统类型两…

WPF 用户控件分享之边上带输入框的圆圈

WPF 用户控件分享之边上带输入框的圆圈独立观察员 2022 年 8 月 20 日最近有这样一个需求,有一圈圆形,每个圆形边上有个输入框,以下是完成后的效果图:拿到这个需求后,分析界面上每个圆形和输入框应该视为一个用户控件&…

Unity 将是驱动 C# 增长的引擎吗 ?

C# 在中国的采用需要一个杀手级应用的带动, 那么这样的一个杀手级应用是 Unity吗,我这里大胆推测采用CoreCLR 的新一代完全采用C#构建的Unity 将是这样的一个杀手级应用。Unity已被广泛应用于数字孪生、数字城市、数字工厂等场景,成为各产业加…

Windows 超级开源实用工具:Microsoft PowerToys

实用工具集: Always on Top ​通过 Always on Top,可使用快捷键方式 (⊞ WinCtrlT) 将窗口固定在其他窗口的顶部。 ​ PowerToys Awake PowerToys Awake旨在使计算机保持唤醒状态,且无需管理其电源和睡眠设置。 运行耗时较长的任务时&#…

Python入门之数据类型

字符串 列表 元组 字典 转载于:https://www.cnblogs.com/py17/p/8919495.html

Kubeadm 快速搭建 k8s v1.24.1 集群(openEuler 22.03 LTS)

kubeadm 简介kubeadm 是 Kubernetes(以下简称 k8s)官方提供的用于快速安装部署 k8s 集群的工具,伴随 k8s 每个版本的发布都会同步更新,kubeadm 会对集群配置方面的一些实践做调整,通过实验 kubeadm 可以学习到 k8s 官方…

汇编试验五:编写、调试具有多个段的程序

ds 数据段放入数据正确; 两次push 操作后,ss栈段正确; 由于pop 操作顺序,ds数据段并没有发生改变; Source Code: assume cs:code, ds:data, ss:stackdata segmentdw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H …

SVN四部曲之SVN设置详解深入

想知道不同的设置是干什么用的,你只需将鼠标指针在编辑框/选项框上停留一秒钟...一个帮助提示气泡就会弹出来。 常规设置 图 4.68. 设置对话框,常规设置页面 这个对话框允许你指定自己喜欢的语言,同时也可做那些与Subversion相关的特殊设置。…

Vue3.2单文件组件setup的语法糖总结

目录 前言 setup语法糖 一、基本用法 二、data和methods 三、计算属性computed 四、监听器watch、watchEffect 五、自定义指令directive 六、import导入的内容可直接使用 七、声明props和emits 八、父组件获取子组件的数据 九、provide和inject传值 十、路由useRou…

使用dotnet-monitor分析在Kubernetes的应用程序:Sidecar模式

dotnet-monitor可以在Kubernetes中作为Sidecar运行,Sidecar是一个容器,它与应用程序在同一个Pod中运行,利用Sidecar模式使我们可以诊断及监控应用程序。如下图所示,这是我们最终要实现的目标,通过可视化界面查看应用程…

SFB 项目经验-07-Skype for Business 话机 Polycom CX700

本系列博文:Lync 项目经验-01-共存迁移-Lync2013-TO-SFB 2015-规划01http://dynamic.blog.51cto.com/711418/1858520 Lync 项目经验-02-共存迁移-Lync2013-TO-SFB 2015-规划02http://dynamic.blog.51cto.com/711418/1859143 Lync 项目经验-03-共存迁移-Lync2013-TO…

亿方云CEO程远:转型第一式:链接企业人与数据

传统企业一直在探讨如何做好互联网转型,那么互联网核心是什么?转型目标是什么?亿方云CEO程远在此次峰会上发表了自己看法,他认为快、人、连接是互联网核心基因,转型第一步就在于企业、人与数据的充分链接。中国企业的互…

使用.NET简单实现一个Redis的高性能克隆版(七-完结)

译者注该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单、高性能兼容Redis协议的数据库的经历。首先这个"Redis"是非常简单的实现,但是他在优化这个简单"Redis"路程很有趣,也能给我们在从事性能优化工作时带来一些启…

解决 Vue 里 Script 标签首层不缩进 - VS Code

问题: 在 vscode 使用 vue 的时候,发现 script 标签首层不缩进??? 下载扩展:prettier 解决方法一: 打开 setting.json文件 添加:"prettier.vueIndentScriptAndStyle": tru…

Android应用开发性能优化完全分析

1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾。不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结、我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只给出啥啥啥不能用&am…

ZBLOG-ASP2.2如何给图片增加ALT标签说明文字?

2019独角兽企业重金招聘Python工程师标准>>> 一直以来,我们在建设网站的时候,都容易犯下一个大错误,那就是没有重视图片的文字说明,而大多数时候,技术方面并不能很好的识别图片的内容,这也是受限…

[asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?

在QQ群或者一些程序的交流平台,经常会有人问:我怎么传一个数组在Action中接收、我传的数组为什么Action的model中接收不到、或者我在ajax的data中设置了一些数组,为什么后台还是接收不了、还有一些怎么传送一个复杂的对象或者Action怎么接收一…

拒绝“高冷”词汇!初学C#中的委托

拒绝“高冷”词汇!初学C#中的委托 有一天,你写了好多好多带“形参”的构造函数(就是“方法”,同义),而且需要向这些构造函数里传递同样的“实参”,然后你就憨憨地一个一个函数的调用并赋予同样的…

JAVA企业级应用TOMCAT实战视频课程

1. Tomcat简介Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器…