1.传统的I/O
使用传统的I/O程序读取文件内容, 并写入到另一个文件(或Socket), 如下程序:
File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);
会有较大的性能开销, 主要表现在一下两方面:
- 上下文切换(context switch), 此处有4次用户态和内核态的切换
- Buffer内存开销, 一个是应用程序buffer, 另一个是系统读取buffer以及socket buffer
其运行示意图如下:
1) 先将文件内容从磁盘中拷贝到操作系统buffer.
2) 再从操作系统buffer拷贝到程序应用buffer.
3) 从程序buffer拷贝到socket buffer.
4) 从socket buffer拷贝到协议引擎.
2. NIO
NIO技术省去了将操作系统的read buffer拷贝到程序的buffer, 以及从程序buffer拷贝到socket buffer的步骤, 直接将 read buffer 拷贝到 socket buffer. java 的 FileChannel.transferTo() 方法就是这样的实现, 这个实现是依赖于操作系统底层的sendFile()实现的.
publicvoid transferTo(long position, long count, WritableByteChannel target);
他的底层调用的是系统调用sendFile()方法
sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
如下图: