Consumer 消费消息过程,使用了零拷贝,零拷贝包含以下两种方式:

    1. 使用 mmap + write 方式
      优点: 即使频繁调用,使用小块文件传输,效率也很高
      缺点: 不能很好的利用 DMA 方式,会比 sendfile 多消耗 CPU,内存安全性控制复杂,需要避免 JVM Crash问题;
    1. 使用 sendfile 方式
      优点:可以利用 DMA 方式,消耗 CPU 较少,大块文件传输效率高,无内存安全新问题。 缺点:小块文件效率低于 mmap 方式,只能是 BIO 方式传输,不能使用 NIO。

      1. <br />RocketMQ 选择了第一种方式,mmap+write 方式,因为有小块数据传输的需求,效果会比 sendfile 更好。metaq 在文件读写的过程中,使用 mmap + write 的方式代替传统的 io 操作,从而减少了文件读写系统调用次数,提升了 io 性能;<br />传统的文件读写:<br />1.系统调用打开文件,获取文件描述符;<br />2.使用 read, write 的系统调用完成文件读写,最终关闭文件;<br />3.这种方式很低效,每次 io 都需要一次系统调用(**用户空间与内核空间切换**);<br />4.如果若干进程访问同一个文件,每个进程都要在自己的地址空间维护一个副本,浪费了内存空间。

    内存映射的方式:
    1.打开文件,得到文件描述符;
    2.获取文件大小;
    3.把文件映射成虚拟内存(mmap);
    4.通过对内存的读写来实现对文件的读写(memset 或 memcpy);
    5. 卸载映射;
    6.关闭文件

    内存映射过程:

    1. 首先建立好虚拟内存和磁盘文件之间的映射(mmap系统调用),当进程访问页面时产生一个缺页中断,内核将页面读入内存(也就是说把磁盘上的文件拷贝到内存中),并且更新页表指向该页面。
    2. 所有进程共享同一物理内存,物理内存中可以只存储一份数据,不同的进程只需要把自己的虚拟内存映射过去就可以了,这种方式非常方便于同一副本的共享,节省内存。
    3. 经过内存映射之后,文件内的数据就可以用内存读/写指令来访问,而不是用Read和Write这样的I/O系统函数,从而提高了文件存取速度。

    参考:1. 中间件学习
    2. 零拷贝