当前位置: 首页 > news >正文

Netty源码解析-零拷贝

Netty基本介绍,参考 Netty与网络编程

摘要

Netty源码系列-Netty如何使用零拷贝

1、零拷贝

Netty为了加快文件传输速度,采用了零拷贝技术。
sendFile(Kafka也是用该技术优化性能):发送文件描述符,如果硬件支持,图二的文件缓冲区和Socket缓冲区可以共享,只需要两次DMA拷贝就可以
在这里插入图片描述

1.1 、源码DefaultFileRegion.transferto()方法

我们看一下源码,Netty的文件传输零拷贝方法就是该方法(如下图),方法下面圈出来的一行是(FileChannel)file.tranferto (java API)就是 sendFile,采用零拷贝技术,省去了从用户空间中转的过程(见上图)
在这里插入图片描述

1.2 我们通过一个案例看一下零拷贝和普通拷贝的区别

我们尝试传输一个大小230M的文件,来看下普通传输和零拷贝性能的差异。
下面我们创建一个普通ServerSocket服务端,一个传统的文件传输方式的TranditionClient,一个零拷贝传输方式的NewIOClient,两者都想服务端传输同一个文件,比较传输时间。代码如下:

1.2.1 首先写一个Server
public class Server {public static void main(String[] args) throws Exception {//创建serversocket 对象--8088服务ServerSocket serverSocket = new ServerSocket(8088);//循环监听连接while (true){Socket socket = serverSocket.accept();//客户端发起网络请求---连接//创建输⼊流对象DataInputStream dataInputStream = newDataInputStream(socket.getInputStream());int byteCount=0;try{byte[] bytes = new byte[1024];        //创建缓冲区字节数组while(true){int readCount = dataInputStream.read(bytes, 0,bytes.length);byteCount=byteCount+readCount;if(readCount==-1){System.out.println("服务端接受:"+byteCount+"字节");break;}}}catch (Exception e){e.printStackTrace();}}}
}
1.2.2 普通文件传输方式
public class TranditionClient {public static void main(String[] args) throws Exception {Socket socket = new Socket("localhost",8088);// 文件大小230MString fileName = "/Users/bing/Downloads/Joplin-3.0.14-arm64.DMG";//创建输⼊流对象InputStream inputStream = new FileInputStream(fileName);//创建输出流DataOutputStream dataOutputStream = newDataOutputStream(socket.getOutputStream());byte[] buffer = new byte[1024];long readCount = 0;long total=0;long startTime = System.currentTimeMillis();//TODO 这里要发生2次copywhile ((readCount=inputStream.read(buffer))>=0){total+=readCount;//TODO 网络发送:这里要发生2次copydataOutputStream.write(buffer);}long endTime = System.currentTimeMillis();System.out.println("发送总字节数:"+total+",耗时:"+(endTime-startTime)+" ms");//释放资源dataOutputStream.close();socket.close();inputStream.close();}
}
1.2.3 零拷贝传输方式
public class NewIOClient {public static void main(String[] args) throws Exception {//socket套接字SocketChannel socketChannel = SocketChannel.open();socketChannel.connect(new InetSocketAddress("localhost",8088));socketChannel.configureBlocking(true);//文件 大小230MString fileName = "/Users/bing/Downloads/Joplin-3.0.14-arm64.DMG";//FileChannel 文件读写、映射和操作的通道FileChannel fileChannel = new FileInputStream(fileName).getChannel();long startTime = System.currentTimeMillis();//transferTo⽅法⽤到了零拷⻉,底层是sendfile,这里只需要发生2次copy和2次上下文切换long transferCount = fileChannel.transferTo(0, fileChannel.size(), socketChannel);long endTime = System.currentTimeMillis();System.out.println("发送总字节数:"+transferCount+"耗时:"+(endTime-startTime)+" ms");//释放资源fileChannel.close();socketChannel.close();}
}
1.2.4 结果

通过多次测试得到结果,零拷贝方式比传统方式快很多,如下:

  • 1)传统传输方式,耗时530ms左右:
    在这里插入图片描述

  • 2)零拷贝方式,耗时150ms左右:
    在这里插入图片描述

总结

零拷贝是一种很重要的IO优化策略,在一些开源软件上都有应用,比如Kafka也使用零拷贝技术来提升吞吐量。


http://www.mrgr.cn/news/34097.html

相关文章:

  • PHP智慧教育新篇章优校管理系统小程序源码
  • 【C++掌中宝】缺省参数的全面解析
  • 数据仓库适用的业务场景
  • 构建高可用和高防御力的云服务架构第五部分:PolarDB(5/5)
  • iOS常见锁及应用(笔记版)
  • IT 人转架构设计必备:项目学习资料+视频分享,涵盖运维管理全内容
  • Iceberg 表不能用 Show Partitions 显示分区信息
  • 路径处理 | 关键点提取之Douglas–Peucker算法(附ROS C++/Python实现)
  • 数据分析:主成分以及贡献变量解析
  • PMP培训机构,雷区注意绕行
  • 防火墙详解(二)通过网页登录配置华为eNSP中USG6000V1防火墙
  • 力扣 困难 154.寻找旋转排序数组中的最小值 II
  • 【PostgreSQL】PostgreSQL数据库允许其他IP连接到数据库(Windows Linux)
  • C++之Count类
  • 语音合成(自然、非自然)
  • doris的be节点buff/cache 持续增大问题
  • 神经网络(一):神经网络入门
  • 【C语言进阶】第四节:自定义类型详解
  • LDO选型
  • HarmonyOS---权限和http/Axios网络请求