介绍

Java 的zero copy多在网络应用程序中使用。Java的libaries在linux和unix中支持zero copy,关键的api是java.nio.channel.FileChannel的transferTo(),transferFrom()方法。我们可以用这两个方法来把bytes直接从调用它的channel传输到另一个writable byte channel,中间不会使data经过应用程序,以便提高数据转移的效率。

许多web应用都会向用户提供大量的静态内容,这意味着有很多data从硬盘读出之后,会原封不动的通过socket传输给用户。这种操作看起来可能不会怎么消耗CPU,但是实际上它是低效的:kernal把数据从disk读出来,然后把它传输给user级的application,然后application再次把同样的内容再传回给处于kernal级的socket。这种场景下,application实际上只是作为一种低效的中间介质,用来把disk file的data传给socket。

data每次穿过user-kernel boundary,都会被copy,这会消耗cpu,并且占用RAM的带宽。幸运的是,你可以用一种叫做Zero-Copy的技术来去掉这些无谓的 copy。应用程序用zero copy来请求kernel直接把disk的data传输给socket,而不是通过应用程序传输。Zero copy大大提高了应用程序的性能,并且减少了kernel和user模式的上下文切换

使用kernel buffer做中介(而不是直接把data传到user buffer中)看起来比较低效(多了一次copy)。然而实际上kernel buffer是用来提高性能的。在进行读操作的时候,kernel buffer起到了预读cache的作用。当写请求的data size比kernel buffer的size小的时候,这能够显著的提升性能。在进行写操作时,kernel buffer的存在可以使得写请求完全异步。

悲剧的是,当请求的data size远大于kernel buffer size的时候,这个方法本身变成了性能的瓶颈。因为data需要在disk,kernel buffer,user buffer之间拷贝很多次(每次写满整个buffer)。

而Zero copy正是通过消除这些多余的data copy来提升性能。

传统的数据复制方式及涉及到的上下文切换:

通过网络把一个文件传输给另一个程序,在OS的内部,这个copy操作要经历四次user mode和kernel mode之间的上下文切换,甚至连数据都被拷贝了四次,如下图:

具体步骤如下:

  1. read() 调用导致一次从user mode到kernel mode的上下文切换。在内部调用了sys_read() 来从文件中读取data。第一次copy由DMA (direct memory access)完成,将文件内容从disk读出,存储在kernel的buffer中。
  2. 然后请求的数据被copy到user buffer中,此时read()成功返回。调用的返回触发了第二次context switch: 从kernel到user。至此,数据存储在user的buffer中。
  3. send() Socket call 带来了第三次context switch,这次是从user mode到kernel mode。同时,也发生了第三次copy:把data放到了kernel adress space中。当然,这次的kernel buffer和第一步的buffer是不同的buffer。
  4. 最终 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层面的使用方法没有变,但是内部原理却发生了变化:

  1. transferTo()方法使得文件内容被copy到了kernel buffer,这一动作由DMA engine完成。
  2. 没有data被copy到socket buffer。取而代之的是socket buffer被追加了一些descriptor的信息,包括data的位置和长度。然后DMA engine直接把data从kernel buffer传输到protocol engine,这样就消除了唯一的一次需要占用CPU的拷贝操作。

零拷贝Zero-Copy(NIO)的更多相关文章

  1. 零拷贝-zero copy

    Efficient data transfer through zero copy Zero Copy I: User-Mode Perspective 0. 前言 在阅读RocketMQ的官方文档时 ...

  2. 对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解

    此文章已同步发布在我的 segmentfault 专栏. 根据 Wiki 对 Zero-copy 的定义: "Zero-copy" describes computer opera ...

  3. 感悟优化——Netty对JDK缓冲区的内存池零拷贝改造

    NIO中缓冲区是数据传输的基础,JDK通过ByteBuffer实现,Netty框架中并未采用JDK原生的ByteBuffer,而是构造了ByteBuf. ByteBuf对ByteBuffer做了大量的 ...

  4. 零拷贝(Zero-copy) 浅析及其应用

    相信大家都有过面经历,如果跟面试官聊到了操作系统,聊到了文件操作,可能会问你普通的文件读写流程,它有什么缺点,你知道有什么改进的措施.我们经常听说 零拷贝,每次可能只是背诵一些面试要点就过去了,今天我 ...

  5. 框架篇:Linux零拷贝机制和FileChannel

    前言 大白话解释,零拷贝就是没有把数据从一个存储区域拷贝到另一个存储区域.但是没有数据的复制,怎么可能实现数据的传输呢?其实我们在java NIO.netty.kafka遇到的零拷贝,并不是不复制数据 ...

  6. Linux文件和零拷贝

    本文转载自文件和零拷贝 文件概述 文件描述符 文件描述符:在Linux中,所有的文件都是通过文件描述符引用.fd是一个非负整数.按照惯例,标准输入的fd是0,标准输出的fd是1,标准错误的fd是2.分 ...

  7. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  8. Linux、JDK、Netty中的NIO与零拷贝

    一.先理解内核空间与用户空间 Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,分别对应着下图中, CPU 特权等级分为4个,Linux 使用 Ring 0 和 Ring 3. 内核空 ...

  9. Netty:Netty中的零拷贝(Zero Copy)

    零复制概念: " 零复制"描述了计算机操作,其中CPU不执行将数据从一个存储区复制到另一个存储区的任务.通过网络传输文件时,通常用于节省CPU周期和内存带宽. WIKI的定义中,我 ...

随机推荐

  1. IDEA常见错误解决

    tomcat控制台乱码 在tomcat的edit configurations里加入参数:-Dfile.encoding=UTF-8   导入的项目在重写时报 @Override is not all ...

  2. 20155230 《Java程序设计》实验五 Java网络编程及安全

    20155230 <Java程序设计>实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验1 两人一组结对编程 ...

  3. 2017-2018-1 20155329《信息安全技术》实验二——Windows口令破解

    2017-2018-1 20155329<信息安全技术>实验二--Windows口令破解 实验原理 口令破解方法 字典破解: 指通过破解者对管理员的了解,猜测其可能使用某些信息作为密码,利 ...

  4. WPF使用IDataErrorInfo接口进行数据校验 - 简书

    原文:WPF使用IDataErrorInfo接口进行数据校验 - 简书 class ValidationBindableBase : BindableBase, IDataErrorInfo { pu ...

  5. [FJOI2016]建筑师 斯特林数

    早期作品,不喜轻喷. LG传送门 组合数与斯特林数的基本应用. 组合数 大家应该都熟悉它的表达式,但我们这里使用它的递推式会更加方便,下面推导组合数的递推式.设\(\binom{n}{m}\)表示在\ ...

  6. (转) 理解Angular中的$apply()以及$digest()

    原文地址:http://blog.csdn.net/dm_vincent/article/details/38705099 $apply()和$digest()在AngularJS中是两个核心概念,但 ...

  7. 使用 AFNetworking做过断点续传吗?

    断点续传的主要思路: 检查服务器文件信息 检查本地文件 如果比服务器文件小, 断点续传, 利用 HTTP 请求头的 content-range实现断点续传(如果content-range不存在就取Co ...

  8. 世界杯足彩怎么买划算?机器学习AI告诉你答案(含预测)

    本文首发于InfoQ公众号头条. 四年一度的世界杯又来了,作为没什么时间看球的码农,跟大家一样,靠买买足彩给自己点看球动力和乐趣, 然而总是买错球队,面对各种赔率也不知道怎么买才划算,足彩是不是碰大运 ...

  9. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

    1. 摘要 训练深层的神经网络非常困难,因为在训练的过程中,随着前面层数参数的改变,每层输入的分布也会随之改变.这需要我们设置较小的学习率并且谨慎地对参数进行初始化,因此训练过程比较缓慢. 作者将这种 ...

  10. Amazon及其亏本诱饵策略还能坚持多久?

    Amazon 刚刚公布了最新的财报,亏损 4100 万美元.这是这家电子商务巨头连续 5 个季度以来的第 3 次亏损.但是华尔街似乎却一片叫好声,当日 Amazon 的股价也涨了近 8 个点达 359 ...