JAVA Zero Copy
2015-08-08 10:52
447 查看
http://my.oschina.net/cloudcoder/blog/299944
java 的zero copy多在网络应用程序中使用。Java的libaries在linux和unix中支持zero copy,关键的api是java.nio.channel.FileChannel的transferTo(),transferFrom()方法。我们可以用这两个方法来把bytes直接从调用它的channel传输到另一个writable byte channel,中间不会使data经过应用程序,以便提高数据转移的效率。
通过网络把一个文件传输给另一个程序,在OS的内部,这个copy操作要经历四次user mode和kernel mode之间的上下文切换,甚至连数据都被拷贝了四次,如下图:
具体步骤如下:
read() 调用导致一次从user mode到kernel mode的上下文切换。在内部调用了sys_read() 来从文件中读取data。第一次copy由DMA (direct
memory access)egine完成,将文件内容从disk读出,存储在kernel的buffer中。
然后请求的数据被copy到user buffer中,此时read()成功返回。调用的返回触发了第二次context switch: 从kernel到user。至此,数据存储在user的buffer中。
send() Socket call 带来了第三次context switch,这次是从user mode到kernel mode。同时,也发生了第三次copy:把data放到了kernel adress space中。当然,这次的kernel buffer和第一步的buffer是不同的buffer。
最终 send() system call 返回了,同时也造成了第四次context switch。同时第四次copy发生,DMA egine将data从kernel buffer拷贝到protocol engine中。第四次copy是独立而且异步的。
在linux 2.4及以上版本的内核中(如linux 6或centos 6以上的版本),开发者修改了socket buffer descriptor,使网卡支持
gather operation,通过kernel进一步减少数据的拷贝操作。这个方法不仅减少了context switch,还消除了和CPU有关的数据拷贝。user层面的使用方法没有变,但是内部原理却发生了变化:
transferTo()方法使得文件内容被copy到了kernel buffer,这一动作由DMA engine完成。
没有data被copy到socket buffer。取而代之的是socket buffer被追加了一些descriptor的信息,包括data的位置和长度。然后DMA engine直接把data从kernel buffer传输到protocol engine,这样就消除了唯一的一次需要占用CPU的拷贝操作。
展示通过网络把一个文件从client传到server的过程
?
?
其它zero copy的用法
?
https://www.ibm.com/developerworks/linux/library/j-zerocopy/
/article/9196927.html
介绍
java 的zero copy多在网络应用程序中使用。Java的libaries在linux和unix中支持zero copy,关键的api是java.nio.channel.FileChannel的transferTo(),transferFrom()方法。我们可以用这两个方法来把bytes直接从调用它的channel传输到另一个writable byte channel,中间不会使data经过应用程序,以便提高数据转移的效率。
传统的数据复制方式及涉及到的上下文切换:
通过网络把一个文件传输给另一个程序,在OS的内部,这个copy操作要经历四次user mode和kernel mode之间的上下文切换,甚至连数据都被拷贝了四次,如下图:具体步骤如下:
read() 调用导致一次从user mode到kernel mode的上下文切换。在内部调用了sys_read() 来从文件中读取data。第一次copy由DMA (direct
memory access)egine完成,将文件内容从disk读出,存储在kernel的buffer中。
然后请求的数据被copy到user buffer中,此时read()成功返回。调用的返回触发了第二次context switch: 从kernel到user。至此,数据存储在user的buffer中。
send() Socket call 带来了第三次context switch,这次是从user mode到kernel mode。同时,也发生了第三次copy:把data放到了kernel adress space中。当然,这次的kernel buffer和第一步的buffer是不同的buffer。
最终 send() system call 返回了,同时也造成了第四次context switch。同时第四次copy发生,DMA egine将data从kernel buffer拷贝到protocol engine中。第四次copy是独立而且异步的。
数据转移(data transfer): zero copy方式及涉及的上下文转换
在linux 2.4及以上版本的内核中(如linux 6或centos 6以上的版本),开发者修改了socket buffer descriptor,使网卡支持gather operation,通过kernel进一步减少数据的拷贝操作。这个方法不仅减少了context switch,还消除了和CPU有关的数据拷贝。user层面的使用方法没有变,但是内部原理却发生了变化:
transferTo()方法使得文件内容被copy到了kernel buffer,这一动作由DMA engine完成。
没有data被copy到socket buffer。取而代之的是socket buffer被追加了一些descriptor的信息,包括data的位置和长度。然后DMA engine直接把data从kernel buffer传输到protocol engine,这样就消除了唯一的一次需要占用CPU的拷贝操作。
代码样例:
展示通过网络把一个文件从client传到server的过程?
?
参考
https://www.ibm.com/developerworks/linux/library/j-zerocopy//article/9196927.html
相关文章推荐
- Java基础-IO-字符输入输出流(笔记)
- java基础教程-多线程编程
- Spring3.x和Hibernate4的整合问题
- JAVA 同步器CountDownLatch CyclicBarrier
- Java基础-IO-字节输入输出流(笔记)
- 高效率的文件复制的Java代码
- JAVA8新特性
- JAVA8新特性
- 用eclipse联合adb截取android设备的log
- 编码剖析Spring依赖注入的原理
- java基础语法1
- Java基础-IO-File(笔记)
- Java 如何得到 JVM 虚拟机的 System Properties
- Java引用传值的问题
- eclipse配置lombok
- Java多线程——<六>更方便的线程
- java Spring 定时任务的几种实现
- springmvc 的参数绑定
- Java中的可变参数
- 客户端跳转与服务器端跳转的区别以及路径