传统 IO:
场景:将磁盘上的文件读取出来,然后通过网络协议发送给客户端。
传统文件IO:产生4次用户上下文切换,4次拷贝。
调用 read 方法读取 index.html 的内容—— 变成字节数组,然后调用 write 方法,将 index.html 字节流写到 socket 中,
那么,我们调用这两个方法,在 OS 底层发生了什么呢?
File file = new File("index.html");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
byte[] arr = new byte[(int) file.length()];
raf.read(arr);
Socket socket = new ServerSocket(8080).accept();
socket.getOutputStream().write(arr);
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
1、第一次数据拷贝:我们调用 read 方法,用户态切换到内核态,同时,DMA 引擎从磁盘读取 index.html 文件,并将数据拷贝到内核缓冲区。
DMA (Direct Memory Access,直接内存存取,即不使用 CPU 拷贝数据到内存,而是 DMA 引擎传输数据到内存,用于解放 CPU)
2、第二次数据拷贝:CPU 将内核缓冲区的数据拷贝到用户缓冲区,同时,发生了一次用内核态到用户态的上下文切换。
3、第三次数据拷贝:我们调用 write 方法,系统将用户缓冲区的数据拷贝到 Socket 缓冲区。此时,又发生了一次用户态到内核态的上下文切换。
4、第四次数据拷贝:数据异步的从 Socket 缓冲区,使用 DMA 引擎拷贝到网络协议引擎。这一段,不需要进行上下文切换。
5、write 方法返回,再次从内核态切换到用户态。
一个系统调用对应两次上下文切换,所以上下文切换次数在一般情况下只可能是偶数。
想要优化文件传输的性能就两个方向,因为这两个是最耗时的
1、减少上下文切换次数
2、减少数据拷贝次数
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。