您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

零拷贝并非万能解决方案:重新定义数据传输的效率极限

时间:2023-09-13 15:45:16  来源:微信公众号  作者:灵墨AI探索室

/ PageCache 有什么作用? /

在我们前面讲解零拷贝的内容时,我们了解到一个重要的概念,即内核缓冲区。那么,你可能会好奇内核缓冲区到底是什么?这个专有名词就是 PageCache,也被称为磁盘高速缓存。也可以看下 windows 下的缓存区:如图所示:

图片图片

零拷贝进一步提升性能的原因在于 PageCache 技术的使用。接下来,我们将详细探讨 PageCache 技术是如何实现这一目标的。

读写磁盘相比读写内存的速度慢太多了,但我们可以采取一种方法来改善这个问题,即将磁盘数据部分缓存到内核中,也就是将其存储在 PageCache 缓存区中。这个过程实际上是通过 DMA(直接内存访问)控制器将磁盘数据拷贝到内核缓冲区中。

然而,需要注意的是,由于内存空间较磁盘空间有限,因此存在一系列算法来确保 pageCache 占用的内存空间不过大。我们在程序运行时都知道存在一种「局部性」,即刚刚被访问的数据在短时间内很可能再次被访问到,概率很高。因此,pageCache 被用作缓存最近访问的数据。可以将 pageCache 看作是 redis,而磁盘则类似于 MySQL。此外,pageCache 还使用了内存淘汰机制,在内存空间不足时,会淘汰最近最久未被访问的缓存。

当在项目中使用 Redis 时,你一定知道如何使用它。和 Redis 类似, PageCache 的工作原理也是一样的。在进程需要访问数据时,它会首先检查 PageCache 是否已经存储了所需的数据。如果数据已经存在于 PageCache 中,内核会直接返回数据;如果数据未被缓存,则会从磁盘读取并将数据缓存到 PageCache 中,以备下次查询时使用。这种方式可以有效提高访问效率。

然而,pageCache 还具有另一个优点,即预读功能。当访问并读取磁盘数据时,实际上需要定位磁盘中的位置。对于机械硬盘而言,这意味着磁头必须旋转到数据所在的扇区位置,然后开始顺序读取数据。然而,旋转磁头这种物理操作对计算机而言非常耗时。为了降低其影响,就出现了预读功能。通过预读功能,可以提前预读下一扇区的数据,减少等待磁头旋转的时间。

比如 read 方法需要读取 32KB 的字节的数据,使其在读取 32KB 字节数据后,继续读取后面的 32-64KB,并将这一块数据一起缓存到 pageCache 缓冲区。这样做的好处在于,如果后续读取需要的数据在这块缓存中命中,那么读取成本会大幅降低。可以类比于 redis 中提前缓存一部分分布式唯一 id 用于插入数据库时的分配操作,这样就无需每次插入前都去获取一遍 id。然而,一般情况下,为了避免可能出现的"毛刺"现象,我们通常会使用双缓存机制来处理。这个双缓存机制可以进一步优化读取操作的效果。

因此,PageCache 的优点主要包括两个方面:首先,它能够将数据缓存到 PageCache 中;其次,它还利用了数据的预读功能。这两个操作极大地增强了读写磁盘时的性能。

但是,你可以想象一下如果你在传输大文件时比如好几个 G 的文件,如果还是使用零拷贝技术,内核还是会把他们放入 pageCache 缓存区,那这样不就产生问题了吗?你也可以想一下如果你往 redis 缓存中放了一个还几个 G 大小的 value,而且还知道缓存了也没用,那不就相当于 redis 形同虚设了吗?把其他热点数据也弄没了,所以 pageCache 也有这样的一个问题,一是大文件抢占了 pageCache 的内存大小,这样做会导致其他热点数据无法存储在 pageCache 缓冲区中,从而降低磁盘的读写性能。此外,由于 pageCache 无法享受到缓存的好处,还会产生一个 DMA 数据拷贝的过程。

因此,最佳的优化方法是针对大文件传输时不使用 pageCache,也就是不使用零拷贝技术。这是因为零拷贝技术会占用大量的内存空间,影响其他热点数据的访问优化。在高并发环境下,这几乎肯定会导致严重的性能问题。

/ 大文件传输用什么方式实现? /

那针对大文件的传输,我们应该使用什么方式呢?

让我们首先来观察最初的示例。当调用 read 方法读取文件时,进程实际上会被阻塞在 read 方法的调用处,因为它需要等待磁盘数据的返回。如下图所示:

图片图片

在没有使用零拷贝技术的情况下,我们的用户进程使用同步 IO 的方式,它会一直阻塞等待系统调用返回数据。让我们回顾一下之前的具体流程:

  1. 应用程序发起 read 系统调用,用户进程开始进行阻塞等待结果返回。
  2. 此时内核会向磁盘发起 I/O 请求,磁盘收到请求后,开始寻址。当磁盘数据准备好后,就会向内核发起 I/O 中断,告知内核磁盘数据已经准备好。
  3. 内核收到中断信号后,将数据从磁盘控制器缓存区拷贝到 pageCache 缓冲区。
  4. 最后,内核会将 pageCache 中的数据再次拷贝到用户缓冲区,也就是用户态的内存中,然后 read 调用返回。

我们知道,既然有同步 IO,就一定有异步 IO 来解决阻塞的问题。异步 IO 的工作方式如下图所示:

图片图片

它将读操作分为两个部分:

  1. 第一部分是用户进程发起 IO 请求给内核,然后进程就不再关心该 IO 操作,而是继续处理其他任务。
  2. 第二部分是当内核接收到中断信号后,将数据直接拷贝到用户缓冲区,并通知用户进程操作成功。然后用户进程开始处理数据。

我们发现在这个过程中,并没有涉及到将数据拷贝到 pageCache 中,因此使用异步方式绕开了 pageCache。直接 IO 是指绕过 pageCache 的 IO 请求,而缓存 IO 是指使用 pageCache 的 IO 请求。通常,对于磁盘而言,异步 IO 只支持直接 IO。

正如前面所提到的,对于大文件的传输,不应该使用 PageCache,因为这可能会导致 PageCache 被大文件占据,从而使得"热点"小文件无法充分利用 PageCache 的优势。

因此,在高并发的场景下,对于大文件传输,我们应该采用"异步 I/O + 直接 I/O"的方式来代替零拷贝技术。

直接 I/O 有两种常见的应用场景:

  1. 首先,如果应用程序已经实现了磁盘数据的缓存,就不需要再次使用 PageCache 进行缓存,这样可以减少额外的性能损耗。例如,在 MySQL 数据库中,可以通过参数设置来开启直接 I/O,避免重复的缓存操作,默认情况下是不开启的。
  2. 其次,在传输大文件时,由于大文件很难命中 PageCache 的缓存,而且会占满 PageCache 导致"热点"文件无法充分利用缓存,增加了性能开销。因此,在这种情况下,应该使用直接 I/O 来绕过 PageCache 的缓存,以提高性能。

需要注意的是,直接 I/O 绕过了 PageCache,因此无法享受内核的两项优化。

  1. 首先,内核的 I/O 调度算法会在 PageCache 中缓存尽可能多的 I/O 请求,然后将它们合并成一个更大的 I/O 请求发送给磁盘,以减少磁盘的寻址操作。
  2. 其次,内核会预读后续的 I/O 请求并将其放入 PageCache 中,同样是为了减少对磁盘的操作。这些优化在直接 I/O 中无法享受到。

于是,当我们需要传输大文件时,我们可以利用异步 I/O 和直接 I/O 的组合来实现无阻塞的文件读取。这种方式可以有效避免 PageCache 的影响,提高文件传输的效率。

因此,在文件传输过程中,我们可以根据文件的大小来选择不同的优化方式,以提高传输效率。对于大文件,使用异步 I/O 和直接 I/O 可以避免 PageCache 的影响;而对于小文件,则可以使用零拷贝技术来减少数据拷贝次数,提高传输速度。

Nginx 中,我们可以通过以下配置来根据文件的大小选择不同的优化方式:

location /video/ { 
    sendfile on; 
    AIo on; 
    directio 1024m; 
}

在这个配置中,我们开启了 sendfile 选项,这允许 Nginx 使用零拷贝技术来传输文件。同时,我们也启用了 aio 选项,这使得 Nginx 可以使用异步 I/O 来提高文件传输的效率。

而通过设置 directio 参数为 1024m,我们告诉 Nginx 当文件大小超过 1024MB 时,使用直接 I/O 来进行文件传输。这意味着在传输大文件时,Nginx 将使用异步 I/O 和直接 I/O 的组合来实现无阻塞的文件读取,避免了 PageCache 的影响。而对于小文件,Nginx 将继续使用零拷贝技术,以减少数据拷贝次数,提高传输速度。

/ 总结 /

至此,我们的计算机基础专栏就结束了,不知道大家有没有发现,操作系统底层提供了丰富的解决方案来支持应用程序的复杂性和可扩展性。对于任何工作中遇到的问题,我们都可以从操作系统的角度寻找解决方法。

今天这一篇其实就是来打破零拷贝的方案神话的,没有一种技术是最好的,只有最合适的方法。我们需要根据具体的需求和情况来选择适合的解决方案,以提高应用程序的性能和可扩展性。谢谢大家的阅读和关注,希望这个专栏能对大家有所启发和帮助!



Tags:零拷贝   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
零拷贝并非万能解决方案:重新定义数据传输的效率极限
/ PageCache 有什么作用? /在我们前面讲解零拷贝的内容时,我们了解到一个重要的概念,即内核缓冲区。那么,你可能会好奇内核缓冲区到底是什么?这个专有名词就是 PageCache,也被称为...【详细内容】
2023-09-13  Search: 零拷贝  点击:(319)  评论:(0)  加入收藏
深入探究 Linux 中的零拷贝技术
零拷贝技术的发展在不同场景下有不同的适用方法。而在Linux操作系统中,现存的零拷贝技术也非常多,它们大部分存在于不同的Linux内核版本,而有些旧的技术已经被新技术所取代。本...【详细内容】
2023-09-04  Search: 零拷贝  点击:(237)  评论:(0)  加入收藏
搞明白什么是零拷贝,就是这么简单
我们总会在各种地方看到零拷贝,那零拷贝到底是个什么东西。接下来,让我们来理一理啊。拷贝说的是计算机里的 I/O 操作,也就是数据的读写操作。计算机可是一个复杂的家伙,包括软...【详细内容】
2023-08-26  Search: 零拷贝  点击:(265)  评论:(0)  加入收藏
零拷贝技术详解
当涉及到网络编程和IO操作时,数据拷贝是一个常见的性能瓶颈。传统的数据拷贝过程中,数据需要从内核缓冲区复制到用户空间缓冲区,然后再从用户空间缓冲区复制到内核缓冲区,这个过...【详细内容】
2023-06-21  Search: 零拷贝  点击:(358)  评论:(0)  加入收藏
一文读懂计算机内核态、用户态和零拷贝技术
存储介质的性能话不多说,先看一张图,下图左边是磁盘到内存的不同介质,右边形象地描述了每种介质的读写速率。一句话总结就是越靠近cpu,读写性能越快。了解了不同硬件介质的读写...【详细内容】
2022-12-02  Search: 零拷贝  点击:(362)  评论:(0)  加入收藏
虚拟内存 & I/O & 零拷贝
作者:mosun,腾讯 PCG 后台开发工程师一、虚拟内存 1.1 虚拟内存引入我们知道计算机由 CPU、存储器、输入/输出设备三大核心部分组成,如下:CPU 运行速度很快,在完全理想的状态下,存...【详细内容】
2022-10-13  Search: 零拷贝  点击:(304)  评论:(0)  加入收藏
如何深入理解零拷贝技术
零拷贝技术是一种思想,指的是计算机操作时,CPU不需要先将数据从某处内存复制从某处内存复制到另一个特定区域。可见,零拷贝的特点是 CPU 不全程负责内存中的数据写入其他组件,CP...【详细内容】
2022-09-14  Search: 零拷贝  点击:(380)  评论:(0)  加入收藏
零拷贝技术
知识补充:1、DMA是直接内存访问(Direct Memory Access) 技术,早期 DMA 只存在在主板上,如今由于 I/O 设备越来越多,数据传输的需求也不尽相同,所以每个 I/O 设备里面都有自己的 D...【详细内容】
2022-06-28  Search: 零拷贝  点击:(327)  评论:(0)  加入收藏
网络IO是如何一步一步走向零拷贝的
你们知道当程序需要读取或者写入数据的时候,CPU是如何操作我们的磁盘的吗?首先CPU肯定是要把读写数据的命令告诉给磁盘,这个命令可以通过IO总线传给磁盘,那这里有个细节,其实我们...【详细内容】
2022-04-12  Search: 零拷贝  点击:(273)  评论:(0)  加入收藏
一文让你彻底搞清楚,Linux零拷贝技术的那些事儿
1.前言像大白这种调包侠,深知不懂底层技术点就如同空中楼阁,再这样下去面阿里p10是没希望了。想到这里,我开始慌了,所以今天和大家一起学习个底层技术点-零拷贝Zero-Copy。Linux...【详细内容】
2022-02-25  Search: 零拷贝  点击:(352)  评论:(0)  加入收藏
▌简易百科推荐
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(5)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(12)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(8)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(5)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(10)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(8)  评论:(0)  加入收藏
为什么都说 HashMap 是线程不安全的?
做Java开发的人,应该都用过 HashMap 这种集合。今天就和大家来聊聊,为什么 HashMap 是线程不安全的。1.HashMap 数据结构简单来说,HashMap 基于哈希表实现。它使用键的哈希码来...【详细内容】
2024-03-22  Java技术指北  微信公众号  Tags:HashMap   点击:(11)  评论:(0)  加入收藏
如何从头开始编写LoRA代码,这有一份教程
选自 lightning.ai作者:Sebastian Raschka机器之心编译编辑:陈萍作者表示:在各种有效的 LLM 微调方法中,LoRA 仍然是他的首选。LoRA(Low-Rank Adaptation)作为一种用于微调 LLM(大...【详细内容】
2024-03-21  机器之心Pro    Tags:LoRA   点击:(12)  评论:(0)  加入收藏
这样搭建日志中心,传统的ELK就扔了吧!
最近客户有个新需求,就是想查看网站的访问情况。由于网站没有做google的统计和百度的统计,所以访问情况,只能通过日志查看,通过脚本的形式给客户导出也不太实际,给客户写个简单的...【详细内容】
2024-03-20  dbaplus社群    Tags:日志   点击:(4)  评论:(0)  加入收藏
Kubernetes 究竟有没有 LTS?
从一个有趣的问题引出很多人都在关注的 Kubernetes LTS 的问题。有趣的问题2019 年,一个名为 apiserver LoopbackClient Server cert expired after 1 year[1] 的 issue 中提...【详细内容】
2024-03-15  云原生散修  微信公众号  Tags:Kubernetes   点击:(6)  评论:(0)  加入收藏
站内最新
站内热门
站内头条