[Netty] NIO和零拷贝

零拷贝指不发生CPU拷贝


传统IO

经历了4次拷贝、三次上下文切换
4次拷贝:

  1. DMA(直接内存拷贝)拷贝到内核buffer
  2. CPU拷贝到用户Buffer
    —用户进行修改操作—
  3. CPU拷贝到SocketBuffer
  4. DMA拷贝到协议栈

mmap内存映射优化

经历了3次拷贝、3次上下文切换(内核缓冲和User缓冲共享数据)
三次拷贝

  1. DMA(直接内存拷贝)
  2. CPU拷贝
    —用户进行修改操作—
  3. DMA拷贝到协议栈

sendFile优化(Linux 2.1)

经历了3次拷贝、2次上下文切换(数据不经过用户态、直接从内核缓冲进入SocketBuffer)

  1. DMA(直接内存拷贝)
  2. CPU拷贝
    —用户进行修改操作—
  3. DMA拷贝到协议栈

sendFile再优化(Linux 2.4)

经历了2次拷贝、2次上下文切换

  1. DMA(直接内存拷贝)
    只有极少的数据需要执行cpu拷贝(长度、偏移量等等)
    —用户进行修改操作—
  2. DMA拷贝到协议栈

mmap和sendFile的区别

  1. mmap适合小数据量的读写,sendFile适合大文件的传输
  2. mmap需要3次上下文切换,3次数据拷贝,sendFile需要2次上下文切换和至少2次数据拷贝

案例

在NIO中实现零拷贝,使用transferTo
服务端代码

public class NewIOService {
    public static void main(String[] args) throws IOException {
        InetSocketAddress address = new InetSocketAddress(7000);

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        ServerSocket serverSocket = serverSocketChannel.socket();

        serverSocket.bind(address);

        // 创建buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        
        while (true){
            SocketChannel socketChannel = serverSocketChannel.accept();

            int readCount = 0;
            while (-1 == readCount){
                readCount = socketChannel.read(byteBuffer);

                byteBuffer.rewind();
            }
        }
    }
}

客户端代码

public class NewIOClient {
    public static void main(String[] args) throws IOException {

        SocketChannel socketChannel = SocketChannel.open();

        socketChannel.connect(new InetSocketAddress("localhost",7000));

        String filename = "1.txt";

        //获取文件Channel
        FileChannel fileChannel = new FileInputStream(filename).getChannel();

        // 准备发送
        long startTime = System.currentTimeMillis();

        // Linux下使用transferTo方法可以完成传输
        // 在windows下一次调用最多发送8M文件,需要分段传输文件,要注意转出时的位置
        long count = fileChannel.transferTo(0, fileChannel.size(), socketChannel);

        System.out.println("发送的总的字节数="+ count+"耗时:"+(System.currentTimeMillis()-startTime));

        // 关闭通道
        fileChannel.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值