4 Star 14 Fork 8

java_wxid/Java知识系统归纳

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
zero-copy.md 2.52 KB
一键复制 编辑 原始数据 按行查看 历史
java_wxid 提交于 2021-04-12 22:33 . netty

零拷贝?

“零拷贝”是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。关于磁盘到网络(或磁盘到磁盘)的拷贝,与底层系统有关,Java 做的是封装。这种零拷贝是不能给我们 Java 程序操作数据的。因为 Java 程序在这里面起到的作用仅仅是发一个“系统调用”(以及封装),其它工作都是内核完成的。

内核 内核是操作系统的软件,它封装了最底层的细节,提供接口,保证安全。Java 程序要调用内核的接口,就涉及 2 次模式切换。调用:从用户模式到内核模式;返回:从内核模式到用户模式。这是耗性能的。内核模式(也叫内核态)拥有比用户模式更大的权限。

系统调用 关于 Java 里的 IO 这一块,相关代码大量调用了 JNI(Java Native Interface),JNI 是由 c/c++ 写的。而这些底层语言关于 IO 这一块,调用的是“系统调用”,“系统调用”是系统内核提供的接口。

虚拟内存 对于 Linux 系统,每个进程分配的内存是虚拟内存,虚拟内存以页为单位分配,并且有页表能找到物理内存的位置。虚拟内存让进程以为自己有连续的内存空间。

传统IO,可以把磁盘的文件经过内核空间,读到JVM空间,然后进行各种操作,最后再写到磁盘或是发送到网络,效率较慢但支持数据文件操作。 零拷贝,直接在内核空间完成文件读取并转到磁盘(或发送到网络)。由于它没有读取文件数据到JVM这一环,因此程序无法操作该文件数据,尽管效率很高!

Netty 的零拷贝主要包含三个方面: Netty 的接收和发送 ByteBuffer 采用 DIRECT BUFFERS,使用堆外直接内存进行 Socket 读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行 Socket 读写,JVM 会将堆内存 Buffer 拷贝一份到直接内存中,然后才写入 Socket 中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。 Netty 提供了组合 Buffer 对象,可以聚合多个 ByteBuffer 对象,用户可以像操作一个 Buffer 那样方便的对组合 Buffer 进行操作,避免了传统通过内存拷贝的方式将几个小 Buffer 合并成一个大的 Buffer。 Netty 的文件传输采用了 transferTo 方法,它可以直接将文件缓冲区的数据发送到目标 Channel,避免了传统通过循环 write 方式导致的内存拷贝问题。

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/java_wxid/Java-knowledge-system-induction.git
git@gitee.com:java_wxid/Java-knowledge-system-induction.git
java_wxid
Java-knowledge-system-induction
Java知识系统归纳
master

搜索帮助

246c6175 1850385 950819b3 1850385