妹妹10分钟就玩懂了零拷贝和NIO,也太强了

微信公众号:moon聊技术
本文约3500字,完整阅读大概会花费你「10分钟」左右的时间
[如果你觉得文章对你有帮助,欢迎关注,点赞,转发]

前言

'零拷贝'这个词大家应该不陌生了,也算是大厂面试中的一个高频考点,玩过 NETTY 的朋友应该对此相当熟悉了,NETTY 的「高并发」很大程度上都是因为 NIO,而 NIO 的核心就是零拷贝技术了,今天就让你十分钟玩懂零拷贝。

传统的IO模型是怎么样的?

我们来看一张图,让我们看看一个文件从磁盘传输到网卡究竟要经历什么样的磨难:
image
  • 「第一步」:将文件通过 「DMA」 技术从磁盘中拷贝到内核缓冲区

  • 「第二步」:将文件从内核缓冲区拷贝到用户进程缓冲区域中

  • 「第三步」:将文件从用户进程缓冲区中拷贝到 socket 缓冲区中

  • 「第四步」:将socket缓冲区中的文件通过 「DMA」 技术拷贝到网卡

这种数据存储的区域整体我们把它叫做「非直接缓冲区」

我们发现,居然有四步数据拷贝的过程!!并且整个数据的传输过程都是「需要 CPU 去执行」的。

这个过程也太繁琐了,我就想传输一些数据,干嘛要传到用户这里,还要我自己再走一遍后续的流程,写到 socket 缓冲区再发出去,你不能帮我实现吗?

怎么去优化传统 IO 的流程呢?

我们继续看上面的流程图理一下,看看哪些步骤是可以去掉的

我们发现在整个过程中,数据从磁盘读出来到发送给网卡,「文件内容」都是「不会发生改变」的,但是我却要经历「4次文件内容的拷贝」才真正能将文件传输到网卡。

那么以最简单的的方式来说,「能不能直接将磁盘中的数据传输到网卡呢?」

当然不可以,这个原因也很简单,因为「网卡和磁盘都是外部设备」,所以一定要有一个中间的缓冲区域来取存储数据,做一个转发的作用。

image

那么我们看上图中能做缓冲的有两个区域,一个是 「socket缓冲区」,一个是「内核缓冲区」,那么用哪一个?

这个问题应该很好选择了,socket 肯定不可以,socket 和我操作系统无瓜,那么只有用内核缓冲区来做缓冲区。

那么能不能通过「内核缓冲区直接给网卡」发送数据呢?

看样子是可以的,那么我们来看看,socket 缓冲区的作用是什么?

socket缓冲区的作用

每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。

write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由 TCP 协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是 TCP 协议负责的事情。

所以socket就是用来「传输网络数据」的,看来没它还不行。

但是我们换个思路,是不是说,只需要「告诉 socket 要传输哪些数据」就可以了?然后文件内容就可以直接用内核缓冲区的就好了。

零拷贝(zero copy)是怎么做到性能提升的

当你读懂了上面的内容,基本上已经能摸到零拷贝的核心脉络了,其实零拷贝就是使用「内存映射」来消除数据拷贝次数的,然后使用 「DMA」 技术来减少CPU的工作时间。

就只从拷贝次数的性能来看,可以讲性能提高至少百分之五十以上。

DMA

上文中经常提到一个很重要的词汇 - DMA ,它在整个零拷贝的流程当中是有很大的占比的,「能帮助 CPU 做大量的工作」,我们来介绍一下这个神奇的技术。

DMA就是「直接存储器访问」,DMA (Direct Memory Access,「直接存储器访问」) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

「原理」:DMA 传输将数据「从一个地址空间复制到另外一个地址空间」。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器来实行和完成。

零拷贝整体流程图

image

看到这里的话相信你对零拷贝已经有了深刻的理解,那么 NIO 到底是什么的?既然说了十分钟让你玩懂 NIO 和零拷贝,那 NIO 必不可少。

为什么需要 NIO ?

所有的系统I/O都分为「两个阶段」

  • 1.等待就绪
  • 2.读写操作

需要说明的是等待就绪的阻塞是不使用CPU的,是在“「空等」”;而真正的读写操作的阻塞是使用CPU的,真正在”干活”,而且这个过程非常快,属于memory copy,带宽通常在1GB/s级别以上,可以理解为「基本不耗时」

我们先来看看传统IO是怎么做的

在传统的 socket IO中,需要为每个连接创建一个线程。

「一个线程对应一个连接,只处理一个连接的事情」,这就是传统的socket IO。

「并发的连接数量非常巨大」时,线程所占用的栈内存和CPU线程「切换的开销就会非常大」

image

在这种情境下还可能会出现「线程数量小于连接数量」的情况,所以每个线程进行 I O操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理。

如上图,假设有三条线程在管理三条连接,如果此时有第四个任务插入,那么就只能等待前面任务执行完成。

image

其操作就像是一条流水线一样,是串行阻塞的,故传统 IO 我们也称为 「BIO」

传统 IO 也「不知道什么时候该处理数据」,所以只能一直傻等。

为了解决这些问题,NIO 就出现了。

NIO 是 怎么解决这些问题的?

我们先来介绍一下 NIO 的核心组件

  • channel(通道)

    • 一个channel(通道)代表和某一实体的连接,这个实体可以是文件、网络套接字等。也就是说,通道是Java NIO提供的一座「桥梁」,用于我们的程序和操作系统底层I/O服务进行交互
  • buffer(缓冲区)
    image
    • 你可以把它理解为存储数据的地方,buffer很重要的三个属性 capacity (总容量),position (指针当前位置),limit (读/写边界位置)
  • selectors(选择器)

    • selector(选择器)是一个特殊的组件,用于采集各个通道的状态(或者说事件)。我们先将「通道注册到选择器,并设置好关心的事件」,然后就可以通过调用select()方法,静静地等待事件发生。

通道有如下4个事件可供我们监听:

Accept:有可以接受的连接

Connect:连接成功

Read:有数据可读

Write:可以写入数据了

我们首先需要注册当这几个事件到来的时候所对应的处理器。然后在合适的时机告诉事件选择器:我对这个事件感兴趣。

image

也就是说,在选择器上注册了这四个事件的处理器,用来处理 channel 的事件,「当 channel 某个事件真的准备就绪了,可以进行下一步的动作时,再告诉服务端来处理相应的数据,把相应的任务分配给服务端」,这样就能更好的利用 cpu 的资源。

前面我们说的零拷贝,就是在这时数据处理时发生的。

NIO 和 IO 有什么区别?

  • 1.NIO是以「缓冲区(块)」 的方式处理数据,IO是以「流」的形式去写入和读出的。
  • 2.NIO 又是基于这种流的形式,采用了通道和缓冲区的形式来进行处理数据的
  • 3.还有一点就是 NIO 的通道是可以「双向」的,但是 IO 中的流只能是「单向」
  • 4.还有就是 NIO 的缓冲区还可以进行分片,可以建立「只读缓冲区、直接缓冲区和间接缓冲区」,直接缓冲区是为加快 I/O 速度,而以一种特殊的方式分配其内存的缓冲区
  • 5.读写触发方式不同,NIO 是以选择器的轮询机制来触发的, IO是收到信息即触发。

总结

从传统 IO 模型 到 NIO 零拷贝模型我们可以看出,一个新技术的产生到崛起肯定是因为「其能满足之前技术满足不了的需求,或者相对于之前技术的性能有很高的提升」

传统 IO 传输需要进行四次的数据内容拷贝,包括「内核态和用户态」的切换,「内核态和数据载体」(磁盘、网卡)的切换,整个过程是阻塞的,过程浪费了很多资源。

而 NIO 是通过选择器,通道等核心模块,将整个 IO 处理过程变为异步的方式,只有其数据任务真正就绪了,才会让 cpu 去做处理,大量的节省了资源,提高了性能。

零拷贝就是让用户态和内核态之间的数据不再通过拷贝的方式传输,使用了「内存映射」,做到了内核态和用户态数据的零拷贝。

其拷贝方式使用了 「DMA」 技术,其目的就是为了解决 CPU 拷贝数据的方式,让「拷贝数据」这种累活「不再占用 CPU 的资源」,有 DMA 去完成。

因为是使用了内存映射的关系,所以零拷贝技术「无法对数据内容做更改」

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容