课程简介:.docx
《课程简介:.docx》由会员分享,可在线阅读,更多相关《课程简介:.docx(13页珍藏版)》请在课桌文档上搜索。
1、端节点算法学端节点算法学是网络算法学在端节点尤其是服务器上的运用。我们可以认为 它是建立高速服务器的一组系统性技术。随着网络功能虚拟化的提出,将来数据中心绝大部分的网络设备都会在通用 服务器上实现,因此端节点算法学的重要性就更突出了。消除不必要的拷贝如果我们跟踪一个网络包从进入网卡到完成处理的整个过程,会发现网络包 在终端中被拷贝了多次,具体场景稍后会看到。为什么我们要把数据拷贝这个问题单独提出来讨论,是因为在计算机中进行 拷贝会消耗两个非常宝贵的资源:内存带宽和内存本身。内存带宽反映了系统读写数据的能力,而访存又是现代计算机系统最大的性 能瓶颈。粗略地说,如果处理一个报文要被拷贝k次,那么系
2、统的吞吐量就可能 降至l/ko计算机内存的容量是确定的,如果一个报文在内存中保存k份,就会降低内 存的有效容量,使得数据在内存和磁盘之间交互的几率增大,访存性能降低。所以说数据拷贝是影响计算机系统性能的重要因素。本章关注如何消除不必 要的拷贝(Pl一个拷贝如果不是由硬件要求的,该拷贝是不必要的。比如, 网络适配器将收到的数据拷贝到计算机内存,这是硬件要求的;然而,数据在内 存之间搬来搬去,比如应用程序和操作系统之间的拷贝,主要是由操作系统的结 构化产生的要求,除此之外没有什么特别的理由,这个拷贝是可以考虑消除的。除了拷贝之外,这一章还将讨论其它影响内存使用效率的操作。5.1 为什么要拷贝数据我
3、们首先看看在终端中数据的多次拷贝是怎么发生的。考虑用户向Web服务 器请求一个静态文件,该文件在磁盘上;Web服务器从磁盘中读出文件,发送到 网络上。我们关注在此过程中,数据在Web服务器中的转移过程。图5.2给出了涉及到的计算机系统的主要部件和拷贝过程。涉及到的主要硬 件为CPU、存储器、内存总线、南桥(10 HUb)、I/O总线、硬盘和网卡,主要 软件为web应用程序和内核程序。这里涉及到两个主要的内核子系统,文件子 系统和网络子系统。文件子系统负责文件管理,网络子系统负责报文收发和协议 处理。为简单起见,图中只画出了一个CPU (许多服务器有多个处理器),并且只 关注对静态内容的请求,即
4、文件直接从磁盘中读出。如果请求的是动态内容, Web服务器后面还需要一个数据库,由服务器侧的一个CGI程序处理请求,从 数据库中读数据,构造网页,再传给Web服务器。注意,图中将文件子系统和网络子系统的代码画在处理器中。实际上,这些 代码也存放在主存中,由处理器从主存中获取。然而,位于处理器指令CaChe中 的代码可以看成是在处理器中的。一个简单的故事直观上,这个故事是很简单的。首先web应用程序通过一个系统调用(如 read()将文件从磁盘读入到它的缓冲区(应用缓冲区);然后构造一个HTTP响 应头,通过一个系统调用(如write()将响应头和缓冲区内容交给网络子系统(TCP/IP程序);网
5、络子系统将数据划分成适当大小的块,加上各层协议头后交 给网络适配器发送。如果讲原理,一般就讲到这个程度。一个真实的故事实际上,这个故事的细节要复杂得多。首先,文件一般先从硬盘读入到一个 称为文件缓冲区的内核空间,我们称COPy 1。这个做法是值得提倡的,这样随后 对该文件的请求就可以直接从内存得到,而不需要每次都去读硬盘。所有的Web 服务器都是这么做的,这样可以极大地减小响应时间。其次,文件数据从文件缓冲区拷贝到Web程序的应用缓冲区,我们称copy 2。接着,Web程序对一个TCP套接字执行一个Write()系统调用。在Writeo调用 中描述的应用缓冲区被拷贝到一个套接字缓冲区,这是内核
6、中不同于文件缓冲区 和应用缓冲区的另一个缓冲区,这称为COPy 3。最后,每个数据块在加上了各层协议头之后,由驱动程序将数据包拷贝到位 于网卡的缓冲区中,发送出去。这称为COPy 4。在传输到网络之前,TCP程序还要扫描一遍数据,计算TCP检查和。以上过程涉及到4次拷贝和1次涉及全部包数据的检查和计算。资源消耗情况我们看一下资源消耗情况。不同内存区域之间的拷贝(COPy 2和COPy 3)需要CPU的参与,每个字都要 通过内存总线读一次和写一次,是消耗资源最多的。计算TCP检查和需对每个字读一次,最后写一个简单结果,因此使用内存总 线一次。涉及外设的拷贝(COPyI和CoPy 4),如果由CP
7、U来做拷贝(称程序输入输 出),其代价与内存区域之间的拷贝一样,每个字都要通过内存总线读、写各一 次。如果由设备来做拷贝(DMA),则每个字只需通过内存总线读一次或写一次。涉及外设的拷贝还会消耗I/O总线带宽(copy 1和COPy 4)。对服务器吞吐量的影响在Web服务器的例子中,即使使用了 DMA,每一个字也要使用内存总线7 次。因此,Web服务器的吞吐量不会超过T/7,其中T为内存速度和内存总线速 度中的较小值。其次,额外的拷贝消耗了内存。在图中,一个文件被存储在文件缓冲区、应 用缓冲区和套接字缓冲区。通常web服务器希望使用尽可能多的文件缓冲区来 避免频繁地访问硬盘。一个文件存在3处,
8、将减少文件缓冲区可用的容量,降低 缓存命中率,从而极大地降低整个服务器的性能。总而言之,多余的拷贝在两个重要的方面损害了服务器的性能:1)由于使 用了过多的总线和内存带宽,使得服务器的运行速度低于总线速度;2)由于使 用了过多的内存,使得服务器不得不大量地去从磁盘读文件,而不是从主存中读 文件。需要注意的是,我们只描述了获取静态内容的情形,实际上相当一部分请求 是关于动态内容的。动态内容通常由一个专门的CGI程序生成,然后通过某种 进程间通信机制交给Web服务程序去发送,这里又会涉及到一次拷贝。下面我们将讨论这些拷贝,哪些是可以避免的,怎么避免。5.2 利用适配器内存消除COPy 4我们首先关
9、注与网络相关的拷贝,即CoPy 4。为什么需要COPy 4? 一个简单的解释是,因为适配器内存位于适配器上,而 内核存储空间位于存储子系统,不在同一个硬件上。但是这个理由并不充分。我们知道在一个内存映射的体系结构中,设备的寄 存器被映射到一块内存区域,CPU通过读写这块内存区域与设备通信。因此从 理论上说,在一个内存映射的体系结构中,内存可以位于总线上的任何地方。所以,尽管内核存储空间通常是位于存储子系统的,但没有理由认为部分内 核空间就不能位于网络适配器中(网络适配器通常包含一定容量的存储器)。利用网络适配器中已有的存储空间(P4)和内核存储空间放置的自由度 (P13),我们可以将套接字缓冲
10、区放在网络适配器中。这样应用缓冲区的内容直 接拷贝到网络适配器的内存中。如何计算检查和?但是这里有一个问题,网络子系统在收发TCP包时需要计算TCP检查和, 如果数据在应用缓冲区和适配器之间直接传递,那么TCP检查和怎么计算呢?这里的一个想法是运用P2c (共享开销)。数据从应用缓冲区拷贝到适配器上 的缓冲区,假如这个拷贝由CPU完成,那么可以让CPU捎带着同时计算检查和。 比如,使用一个寄存器,对已经传输的数据进行累加。但是这个方法有个致命的 问题,就是在接收数据包的时候,CPU边拷贝数据边计算检查和,当发现数据 接收错误时,数据已经进入到应用缓冲区中,这是违背TCP语义的。所以这个 方法从
11、未被实施。后来这个方法被HP实验室的研究人员采纳,应用到他们的网络适配器(称 为Afterburner)中。数据传输不是由CPU完成,而是由网卡通过DMA完成。 由于CPU不参与DMA过程,因此检查和计算是由网卡完成的。这种网卡称为TCP卸载引擎,它将TCP的数据传输下放到网卡上完成,以 减轻CPU的负担。需要注意的是,考虑到TCP连接管理的复杂性,TCP连接的 管理(建立、关闭等)仍由主CPU完成,只是将建立好的TCP连接移交给网络 适配器。这种方法的问题是,网络适配器需要很大的内存空间和较强的处理器来支持 大量的TCP连接,网卡成本很高。5.3 消除 copy 3下面考虑消除COPy 3。
12、注意,我们现在是独立地考虑每一种数据拷贝的消除 方法,这些措施能否组合使用需要仔细考虑。应用和内核之间需要一次拷贝有两个原因。(1)应用和内核使用不同的虚拟 地址空间,需要通过拷贝传递数据。但是这个理由不是充分的,因为完全可以通 过内存映射,将套接字缓冲区映射给应用程序使用。(2) SOCketAPl使用拷贝语 义,应用程序在将缓冲区的内容写入套接字(交给网络子系统)后,它可以往缓 冲区中写入新的数据。但是TCP通常需要缓存数据以备重发,因此TCP不能与 应用共用一块缓冲区,需要通过数据拷贝来解除应用和内核之间的耦合。第2个理由使得拷贝看起来是必要的。如果不能避免拷贝,那我们就考虑能 否减小拷
13、贝的开销?我们可以换个角度想,如果应用不需要立即写缓冲区,或者 很多情况下不需要立即写缓冲区,那么其实应用和内核共用一块缓冲区是安全 的;仅当应用需要写缓冲区、而缓冲区中的数据还没有发走时,这时候才会出问 题。那我们能否等到这种情况发生时才去执行拷贝呢?这就是写时拷贝。写时拷贝有些操作系统(如Mac)提供写时拷贝(copy-on-write)功能,在很多情况 下可以避免实际的拷贝。写时拷贝的实现写时拷贝的基础是虚拟内存。我们用一个例子说明写时拷贝的实现。假定进 程Pl的虚拟页X映射到物理页L,需要复制X的内容到进程P2的虚拟页Yo写时拷贝(续):不幸的是,许多操作系统(如UNIX和WindoW
14、S)不提供写时拷贝。但是理 解了写时拷贝的原理之后,类似的效果是可以实现的。因为现代计算机都使用虚拟内存,通过修改页表来避免物理拷贝是能够做到 的,只是需要找到一种替代CoW位的保护机制。(COW保护机制采用硬件检测、 触发操作系统异常来解决)5.4 优化页面重映射写时拷贝的例子忽略了很多细节,以致于让人觉得页面重映射是很简单的一 个操作,一个大的缓冲区通过一个写页表操作就可以从应用程序传递到内核(或 反过来)。比如在图5.5中,假定操作系统希望将进程Pl的虚拟页10 (VT 10)拷贝到 进程P2 (如内核)的虚拟页8 (VT8),其中VTlO指出一个存放包数据的物理 页。过于简单的想法是只
15、需要修改VT 8的页表表项,使其指向存放包数据的物 理页就可以了。这种过于简单的看法是很误导人的。页面重映射的开销有好几个额外的开销被这种简单的描述给掩盖了。(1)多级页表大多数现代的计算机系统使用多级页表映射(至少有两级),实际映射时可 能要求修改多级页表,由此可能涉及多次写。为了实现跨平台运行,有些操作系统同时维护了机器无关页表和机器相关页 表,则涉及的写操作更多。当页表不在内存中时,还需要在内存中为页表分配一个物理页帧,将页表调 入物理页帧中,为此还需要修改目录页。(若使用32位的虚拟地址和4KB的页,一个进程可以有约一百万个页,所以页 表也要分页。32位机器一般使用两级页表:每1024
16、个页表项组成一个页表,这 些页表的起始地址(即页表所在的物理页帧号)保存在一个目录页中;目录页有 1024个表项,目录页的起始地址保存在一个全局寄存器中。虚拟地址的前10位 用于查找目录页,得到页表的地址;虚拟地址的中间10位用于查找页表,得到 虚拟页的物理页帧号。当包含虚拟页页号的页表已经在内存中时,页面映射只需 修改对应的页表项;当页表不在内存中时,还需要在内存中为页表分配一个物理 页帧,将页表调入物理页帧中,为此还需要修改目录页。)(2)要求锁页表是共享资源,修改页表必须用锁保护,因此修改页表前后要有请求锁和 释放锁的开销。(3)刷新TLB为节省地址转换时间,常用的页表映射缓存在TLB中
17、。当一个新的虚拟页 的地址映射写入页表时,相关的TLB表项要清除或修正。(TLB只包括最近用到 的虚拟页号,指令和数据页分开记录。TLB分别保存64个最常用的指令和数据 的虚拟页号,每个TLB项包括一个虚拟页号和相应的物理页帧号。)(4)在目标域中分配虚拟内存需要为目标进程分配一个新的虚拟页(malloc)。新的虚拟页需要向系统去申 请,为此,系统需要做一些计算在目标进程中找到一个空闲的页表表项。(5)锁住相应的页物理页可能会被换出到磁盘上。为防止页被换出,页必须被锁住,这也需要 开销。所有这些开销在多处理器系统中会被放大(以上不少操作都需要加锁,如 malloc)o其结果是,尽管页表映射看起
18、来非常好,即无论包大小如何,页面重 映射只需常数时间,但这个常数因子实际上是一个很大的开销(Q4),有研究人 员在90年代早期的实验中证实了这一点。也就是说,如果只是简单地使用页表 重映射来避免拷贝,结果可能不像预期的那么好。那么怎么办?数据拷贝开销很大,但页面重映射看起来开销也不小,搞不好 比拷贝一个数据包的开销还要大。那是不是说页面重映射就不能用了呢?不能一 概而论,一次页面重映射的开销很大,有没有办法分摊这个开销呢?研究人员发明了一个称为fbufs (fast buffers的简称)的操作系统设施,可以 消除前4种页面映射开销的全部或大部分。Fbufs (fast buffers)Fbu
19、fs基于这样的观察:如果一个应用正在通过内核向网络发送大量的数据 包,那么一个缓冲区可能会被重用多次。方法一:提前分配好需要的包缓冲区,并计算好所有的页面映射信息(P2a), 发送时重复使用这些包缓冲区。问题是不好预先估计所要的缓冲区数量。方法二:当数据传输开始时才按需分配包缓冲区并计算页面映射(P2b),然 后将其缓存起来(PHa)供后续数据包使用。尽管前几个包的延迟较大,但后续 的包就免除了页面映射的开销。不管哪一种方法,都可以做到“映射一次,重复使用二当需要传输的数据 量很大时,页面映射的开销被平摊,可以认为开销为零。为应用分配一组固定的物理页为避免用户空间和内核空间之间的拷贝,将一组物
20、理页Pl、P2同时映射到内核和应用的页表中,供它们使用。考虑到端系统上可能同时运行多个应用。为进行安全隔离,设计者将数据包 经过的一系列处理程序(一个有序的安全域序列)定义为一条路径,并为每一条 路径预留不同的一组物理页。图5.6是一个路径的例子,以太网软件实现为一个内核级的驱动,TCP/IP栈 实现为一个内核级的安全域,Web应用实现在应用层。图中存在两条接收路径: (以太网,TCP/IP, web),(以太网,OSI, FTP)o将一定数量的物理页映射给 接收路径(以太网、TCP/IP和Web应用),再将另一组物理页映射给另一条接收 路径。这样,每一个应用使用一组固定的物理页。为使该设计发
21、挥作用,当一个数据包到达时,最底层的驱动(甚至是网络适 配器)必须立即判断该数据包要被映射到哪条路径,从而将数据包拷贝到分配给 这条路径的物理页中,这个功能称为提前解复用(early demultiplexing)o在图5.6 中,这是通过检查数据包的所有头部来确定的,比如,具有以太帧头、IP头、 TCP头和端口 80的包属于路径Io映射到同一个物理页的虚拟页号相同在前面的例子中,在同一条路径的进程间传递的是缓冲区描述符。想一想, 在进程间传递缓冲区描述符会有什么问题?理论上,各个进程映射到同一个物理页上的虚拟页号可能不同。比如,第一 个进程的虚拟页10可能和第二个进程的虚拟页8映射到同一个物
22、理页上。这是 很麻烦的,因为第二个进程读入VTlO的描述符后,它必须要知道它对应了自己 的虚拟页8o为避免这种情况,设计者规定映射到同一个物理页的虚拟页号必须相同。为 此,系统将所有进程的虚拟内存中一定数量的起始页预留为fbuf页。收包处理过程图中是只有两个安全域的一条路径。进程I(Writer)收到数据包后,从free fbufs队列取一个空闲缓冲区的描述符,将数据包写入该空闲缓冲区,然后将该 缓冲区的描述符写入written fbufs队列;进程2从written fbufs队列中取包缓冲 区描述符,从相应的包缓冲区中读数据处理,将释放的包缓冲区描述符写回到 free fbufs 队列。到
23、目前为止,接收路径的问题解决了。网卡驱动将数据包装入一个空闲的包 缓冲区,包缓冲区的描述符沿着接收路径传递,每个进程访问同一个物理内存页 进行数据包处理,数据包处理完后,包描述符归还给驱动程序进行重用,在此过 程中没有发生物理拷贝。那么发送路径呢?如何添加包头?在发送路径上,每一个安全域都要给数据包加上一个包头。然而为了实现安 全保护,我们对于每条路径只允许一个写者,其余为读者,这意味着页只能由写 者来修改。那么,怎么允许其它进程添加包头呢?应用如何使用fbufs?现在还剩下一个重要的问题。大量已有的应用软件是使用标准拷贝语义的 SoCketAPl书写的,即应用执行了 Write()系统调用后
24、,就可以重用包缓冲区甚至 释放了。然而使用了 fbufs之后,在包缓冲区被其它进程使用完之前,应用是不 允许写或释放包缓冲区的。这个问题怎么解决呢?修改应用API该问题最终的解决方案是:APl不再保持拷贝语义,应用必须判断能不能写 fbufso当一个fbuf被交给内核后,应用不能写这个fbuf,直至其被归还到空闲 链表中。为防止出错或恶意的代码,当一个fbuf从应用转递到内核后,内核翻转一个 写允许比特,归还fbuf时再重新设置该位。如果应用在不允许写的情况下做了 一次写操作,则会产生一个异常,应用崩溃,但不会影响其它的进程。已有的网络应用软件必须重写吗?改变APl听起来是一个很大的改动,这是
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 课程 简介
链接地址:https://www.desk33.com/p-100552.html