美文网首页
NIO与零拷贝

NIO与零拷贝

作者: 南园故剑00 | 来源:发表于2020-06-07 12:13 被阅读0次

1 零拷贝原理

1.1 传统IO4次拷贝3次切换


2.1优化后3次拷贝2次切换

零拷贝是从操作系统角度看的,是没有CPU拷贝

一次CPU拷贝

mmap将用户空间的一块地址和内核空间的一块地址同时映射到相同的一块物理地址,不管是用户空间还是内核空间都是虚拟地址,最终要通过地址映射映射到物理内存地址。
这种方式避免了内核空间与用户空间的数据交换。IO复用中的epoll函数中就是使用了mmap减少内存拷贝。

2. 代码示例

传统IO

package com.sgg.copyZero;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @description: Java Io 的服务器
 * @date : 2020/6/7 11:29
 * @author: zwz
 */
public class OldIoServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7001);
        while (true) {
            Socket socket = serverSocket.accept();
            DataInputStream inputStream = new DataInputStream(socket.getInputStream());
            try {
                byte[] bytes = new byte[4096];
                while (true) {
                    int read = inputStream.read(bytes, 0, bytes.length);
                    if (read == -1) {
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
package com.sgg.copyZero;

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * @description: Java Io 的服务器
 * @date : 2020/6/7 11:29
 * @author: zwz
 */
public class OldIoClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.1.1", 7001);
        FileInputStream inputStream = new FileInputStream("E:\\resource\\apache-tomcat-v8.5.24.zip");
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

        byte[] buffer = new byte[4096];
        long readCount = 0;
        long total = 0;
        long startTime = System.currentTimeMillis();
        while ((readCount = inputStream.read(buffer)) > 0) {
            total += readCount;
            dataOutputStream.write(buffer);
        }

        System.out.println("发送总字节数:" + total + ",耗时" + (System.currentTimeMillis() - startTime) + "ms");
        dataOutputStream.close();
        socket.close();
        inputStream.close();
    }
}

NIO

package com.sgg.copyZero;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

/**
 * @description:
 * @date : 2020/6/7 11:42
 * @author: zwz
 */
public class NewIOClient {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        //向服务器发送链接,一个通道代表一条TCP链接
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 7002));
        FileChannel fileChannel = new FileInputStream("E:\\resource\\apache-tomcat-v8.5.24.zip").getChannel();

        long l = System.currentTimeMillis();

        //在linux下一个 transferTo 方法就可以完成传输
        //在windows下一次调用 transferTo 只能发送8m,就需要分段传输文件,而且要注意传输的位置
        //transferTo底层使用零拷贝
        long count = fileChannel.transferTo(0, fileChannel.size(), socketChannel);
        System.out.println("发送的总的字节数=" + count + ",耗时:" + (System.currentTimeMillis() - l));
    }
}
package com.sgg.copyZero;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * @description:
 * @date : 2020/6/7 11:42
 * @author: zwz
 */
public class NewIOServer {
    public static void main(String[] args) throws IOException {
        InetSocketAddress inetSocketAddress = new InetSocketAddress(7002);
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        ServerSocket serverSocket = serverSocketChannel.socket();
        serverSocket.bind(inetSocketAddress);

        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            int readCount = 0;
            while (-1 != readCount) {
                try {
                    readCount = socketChannel.read(byteBuffer);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                byteBuffer.rewind(); //倒带 position=0。
            }
        }
    }
}

相关文章

  • NIO与零拷贝

    一、是什么 先来看如下一段代码: 这段代码就是读取一个文件,然后再把它写出去,看起来就几行代码,其实涉及到多次拷贝...

  • NIO与零拷贝

    1 零拷贝原理 1.1 传统IO4次拷贝3次切换 2.1优化后3次拷贝2次切换 零拷贝是从操作系统角度看的,是没有...

  • NIO零拷贝

    先来偷个图,然后扶好小板凳,别摔着了。这是传统IO的文件操作 假设有以下场景,浏览器请求磁盘上的文件a.txt,那...

  • NIO & 零拷贝

    DMA:direct memory access,直接内存拷贝,不使用CPU

  • Netty之二NIO与零拷贝

    个人专题目录 1. Nio与零拷贝 零拷贝是服务器网络编程的关键,任何性能优化都离不开。在 Java 程序员的世界...

  • JVM

    直接内存 使用场景:Unsafe类、NIO零拷贝、Netty的零拷贝、JNI 优点:性能更高 缺点:内存泄漏难排查...

  • NIO-零拷贝

    首先,调用read时,数据文件A拷贝到了kernel模式; 之后,CPU控制将kernel模式数据复制到user模...

  • Netty ByteBuf

    与NIO的ByteBuffer相比可以自定义缓冲区。零拷贝。容量按需增长。读与写模式不需要flip()方法。读和写...

  • 什么是 NIO?

    1、前言 想必大家肯定被什么公众号什么非阻塞、零拷贝、NIO 之类的搞的头了吧,但其实 Java 的 NIO 概念...

  • Nio中文件映射和零拷贝

    NIO中文件映射和零拷贝 Zero-Copy DMA从拷贝至内核缓冲区 cpu将数据从内核缓冲区拷贝至内核空间(s...

网友评论

      本文标题:NIO与零拷贝

      本文链接:https://www.haomeiwen.com/subject/sduqtktx.html