日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

當(dāng)涉及到網(wǎng)絡(luò)編程和IO操作時(shí),數(shù)據(jù)拷貝是一個(gè)常見的性能瓶頸。傳統(tǒng)的數(shù)據(jù)拷貝過程中,數(shù)據(jù)需要從內(nèi)核緩沖區(qū)復(fù)制到用戶空間緩沖區(qū),然后再?gòu)挠脩艨臻g緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū),這個(gè)過程會(huì)耗費(fèi)大量的CPU時(shí)間和內(nèi)存帶寬,降低系統(tǒng)的性能和吞吐量。

為了解決這個(gè)問題,零拷貝技術(shù)應(yīng)運(yùn)而生。零拷貝技術(shù)是指在數(shù)據(jù)傳輸過程中,避免將數(shù)據(jù)從一塊內(nèi)存拷貝到另一塊內(nèi)存,從而減少了CPU的開銷和內(nèi)存帶寬的消耗,提高了系統(tǒng)的性能。

在JAVA后端開發(fā)中,使用零拷貝技術(shù)可以有效提升系統(tǒng)的性能和吞吐量。本文將介紹零拷貝技術(shù)的概念、實(shí)現(xiàn)原理以及在Java后端開發(fā)中的應(yīng)用,希望能夠?yàn)樽x者提供有價(jià)值的參考和幫助。

一、傳統(tǒng)I/O

在展開說零拷貝之前,我們先來回顧一下傳統(tǒng)IO的方式是怎么樣的。

早期的數(shù)據(jù)IO,由用戶進(jìn)程向CPU發(fā)起,應(yīng)用程序與磁盤之間的 I/O 操作都是通過 CPU 的中斷完成的。CPU還要負(fù)責(zé)將磁盤緩沖區(qū)拷貝到內(nèi)核緩沖區(qū)(pageCache),再?gòu)膬?nèi)核緩沖區(qū)拷貝到用戶緩沖區(qū)。為了減少CPU占用,產(chǎn)生了DMA技術(shù),大大解放了CPU。

DMA 的全稱叫直接內(nèi)存存取(Direct Memory Access),是一種允許外圍設(shè)備(硬件子系統(tǒng))直接訪問系統(tǒng)主內(nèi)存的機(jī)制。目前大多數(shù)的硬件設(shè)備,包括磁盤控制器、網(wǎng)卡、顯卡以及聲卡等都支持 DMA 技術(shù)。

1.1傳統(tǒng)I/O的問題

我們以讀取一張圖片數(shù)據(jù)的過程為例來分析傳統(tǒng)IO有哪些問題。傳統(tǒng)的訪問方式是通過 write() 和 read() 兩個(gè)系統(tǒng)調(diào)用實(shí)現(xiàn)的,通過 read() 函數(shù)讀取圖片到到緩存區(qū)中,然后通過 write() 方法把緩存中的圖片輸出到網(wǎng)絡(luò)端口。

read操作:

當(dāng)應(yīng)用程序執(zhí)行 read 系統(tǒng)調(diào)用讀取一塊數(shù)據(jù)的時(shí)候,如果這塊數(shù)據(jù)已經(jīng)存在于用戶進(jìn)程的頁(yè)內(nèi)存中,就直接從內(nèi)存中讀取數(shù)據(jù)。

如果數(shù)據(jù)不存在,則先將數(shù)據(jù)從磁盤加載數(shù)據(jù)到內(nèi)核空間的讀緩存(read buffer)中,再?gòu)淖x緩存拷貝到用戶進(jìn)程的頁(yè)內(nèi)存中。

write操作:

當(dāng)應(yīng)用程序準(zhǔn)備好數(shù)據(jù),執(zhí)行 write 系統(tǒng)調(diào)用發(fā)送網(wǎng)絡(luò)數(shù)據(jù)時(shí),先將數(shù)據(jù)從用戶空間的頁(yè)緩存拷貝到內(nèi)核空間的網(wǎng)絡(luò)緩沖區(qū)(socket buffer)中,然后再將寫緩存中的數(shù)據(jù)拷貝到網(wǎng)卡設(shè)備完成數(shù)據(jù)發(fā)送。

從上圖中可以看出,整個(gè)IO的過程需要進(jìn)行兩次DMA拷貝,兩次CPU拷貝,四次上下文切換。總共四次拷貝,四次切換。這個(gè)代價(jià)確實(shí)有些大。

說完傳統(tǒng)IO,接下來我們看下零拷貝都做了哪些優(yōu)化。

二、零拷貝

2.1什么是零拷貝

零拷貝這個(gè)詞,在很多地方都出現(xiàn)過,比如Kafka、Nginx、Tomcat等等這些技術(shù)的底層都有用到零拷貝技術(shù),那么究竟什么是零拷貝呢?

零拷貝是指在數(shù)據(jù)傳輸過程中,避免了數(shù)據(jù)的多次拷貝,從而提高了數(shù)據(jù)傳輸?shù)男省T趥鹘y(tǒng)的IO模型中,數(shù)據(jù)從磁盤中讀取到內(nèi)核緩沖區(qū),然后再?gòu)膬?nèi)核緩沖區(qū)拷貝到用戶緩沖區(qū),最后再?gòu)挠脩艟彌_區(qū)拷貝到應(yīng)用程序中。而在零拷貝模型中,數(shù)據(jù)可以直接從內(nèi)核緩沖區(qū)拷貝到應(yīng)用程序中,避免了數(shù)據(jù)的多次拷貝,提高了數(shù)據(jù)傳輸?shù)男省A憧截惣夹g(shù)可以通過mmap和sendfile等系統(tǒng)調(diào)用實(shí)現(xiàn)。

所以說零拷貝并不是說不拷貝,而是減少拷貝的次數(shù),因?yàn)閺拇疟P中拷貝數(shù)據(jù)到內(nèi)存,或者從內(nèi)存中的一塊兒區(qū)域拷貝到另一塊兒區(qū)域都是一個(gè)耗費(fèi)性能的操作。零拷貝技術(shù)的目的就是減少這種行為的發(fā)生次數(shù)以此來提高性能。

2.2零拷貝實(shí)現(xiàn)的幾種方式

對(duì)比開頭說到的傳統(tǒng)IO,我們可以在以下幾個(gè)方面進(jìn)行優(yōu)化

1. 用戶態(tài)可以直接操作讀寫,不需要在用戶態(tài)和內(nèi)核態(tài)之間反復(fù)橫跳。

2. 盡量減少拷貝次數(shù),盡量減少上下文切換次數(shù)。

3. 寫時(shí)復(fù)制,需要寫操作的時(shí)候再拷貝,只是讀操作沒必要拷貝

用戶態(tài)直接IO

用戶態(tài)直接 I/O 使得應(yīng)用進(jìn)程或運(yùn)行在用戶態(tài)(user space)下的庫(kù)函數(shù)直接訪問硬件設(shè)備。

用戶態(tài)直接 I/O 只能適用于不需要內(nèi)核緩沖區(qū)處理的應(yīng)用程序,這些應(yīng)用程序通常在進(jìn)程地址空間有自己的數(shù)據(jù)緩存機(jī)制,稱為自緩存應(yīng)用程序,如數(shù)據(jù)庫(kù)管理系統(tǒng) 就是一個(gè)代表。

其次,這種零拷貝機(jī)制會(huì)直接操作磁盤 I/O,由于 CPU 和磁盤 I/O 之間的執(zhí)行時(shí)間差距,會(huì)造成大量資源的浪費(fèi),解決方案是配合異步 I/O 使用。

寫時(shí)復(fù)制

寫時(shí)復(fù)制指的是當(dāng)多個(gè)進(jìn)程共享同一塊數(shù)據(jù)時(shí),如果其中一個(gè)進(jìn)程需要對(duì)這份數(shù)據(jù)進(jìn)行修改,那么就需要將其拷貝到自己的進(jìn)程地址空間中。

這樣做并不影響其他進(jìn)程對(duì)這塊數(shù)據(jù)的操作,每個(gè)進(jìn)程要修改的時(shí)候才會(huì)進(jìn)行拷貝,所以叫寫時(shí)拷貝。

減少拷貝次數(shù)

1. mmap+write零拷貝技術(shù)

以mmap+write的方式替代傳統(tǒng)的read+write的方式,減少了一次拷貝。

mmap 是 linux 提供的一種內(nèi)存映射文件方法,即將一個(gè)進(jìn)程的地址空間中的一段虛擬地址映射到磁盤文件地址使用 mmap 的目的是將內(nèi)核中讀緩沖區(qū)(read buffer)的地址與用戶空間的緩沖區(qū)(user buffer)進(jìn)行映射。從而實(shí)現(xiàn)內(nèi)核緩沖區(qū)與應(yīng)用程序內(nèi)存的共享,省去了將數(shù)據(jù)從內(nèi)核讀緩沖區(qū)(read buffer)拷貝到用戶緩沖區(qū)(user buffer)的過程。

整個(gè)拷貝過程會(huì)發(fā)生 4 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。mmap 主要的用處是提高 I/O 性能,特別是針對(duì)大文件。對(duì)于小文件,內(nèi)存映射文件反而會(huì)導(dǎo)致碎片空間的浪費(fèi)。

2. Sendfile零拷貝技術(shù)

通過 Sendfile 系統(tǒng)調(diào)用,數(shù)據(jù)可以直接在內(nèi)核空間內(nèi)部進(jìn)行 I/O 傳輸,從而省去了數(shù)據(jù)在用戶空間和內(nèi)核空間之間的來回拷貝。

將要讀取的文件緩沖區(qū)的文件 fd 和要發(fā)送的Socket緩沖區(qū)的Socket fd 傳給sendfile函數(shù),Sendfile 調(diào)用中 I/O 數(shù)據(jù)對(duì)用戶空間是完全不可見的。也就是說,這是一次完全意義上的數(shù)據(jù)傳輸過程。也就是說用戶程序不能對(duì)數(shù)據(jù)進(jìn)行修改,而只是單純地完成了一次數(shù)據(jù)傳輸過程。整個(gè)拷貝過程會(huì)發(fā)生 2 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。

3. Sendfile+DMA gather copy

它只適用于將數(shù)據(jù)從文件拷貝到 socket 套接字上的傳輸過程。

它將內(nèi)核空間的讀緩沖區(qū)(read buffer)中對(duì)應(yīng)的數(shù)據(jù)描述信息(內(nèi)存地址、地址偏移量)記錄到相應(yīng)的網(wǎng)絡(luò)緩沖區(qū)( socket buffer)中,由 DMA 根據(jù)內(nèi)存地址、地址偏移量將數(shù)據(jù)批量地從讀緩沖區(qū)(read buffer)拷貝到網(wǎng)卡設(shè)備中。

這樣 DMA 引擎直接利用 gather 操作將頁(yè)緩存中數(shù)據(jù)打包發(fā)送到網(wǎng)絡(luò)中即可,本質(zhì)就是和虛擬內(nèi)存映射的思路類似。

整個(gè)拷貝過程會(huì)發(fā)生 2 次上下文切換、0 次 CPU 拷貝以及 2 次 DMA 拷貝。

4.Splice零拷貝技術(shù)

Splice相當(dāng)于在Sendfile+DMA gather copy上的提升,Splice 系統(tǒng)調(diào)用可以在內(nèi)核空間的讀緩沖區(qū)(read buffer)和網(wǎng)絡(luò)緩沖區(qū)(socket buffer)之間建立管道(pipeline),從而避免了兩者之間的 CPU 拷貝操作。

基于 Splice 系統(tǒng)調(diào)用的零拷貝方式,整個(gè)拷貝過程會(huì)發(fā)生 2 次上下文切換,0 次 CPU 拷貝以及 2 次 DMA 拷貝。

2.3總結(jié)

無論是傳統(tǒng)I/O拷貝方式,還是引入了零拷貝的方式,2次DMA Copy都是必要的步驟,因?yàn)閮纱蜠MA都是依賴硬件完成的。

三、零拷貝的實(shí)際應(yīng)用

3.1JavaNIO基于零拷貝的實(shí)現(xiàn)

Java-NIO:主要有三個(gè)方面用到了零拷貝技術(shù):

MAppedByteBuffer.map():底層調(diào)用了操作系統(tǒng)的mmap()內(nèi)核函數(shù)。

DirectByteBuffer.allocateDirect():可以直接創(chuàng)建基于本地內(nèi)存的緩沖區(qū)。

FileChannel.transferFrom()/transferTo():底層調(diào)用了sendfile()內(nèi)核函數(shù)。

3.2主流技術(shù)中零拷貝的應(yīng)用

1..NETty中零拷貝的應(yīng)用

Netty中的零拷貝是一種用戶進(jìn)程級(jí)別的零拷貝體現(xiàn),主要也包含三方面:

1) Netty的發(fā)送、接收數(shù)據(jù)的ByteBuf緩沖區(qū),默認(rèn)會(huì)使用堆外本地內(nèi)存創(chuàng)建,采用直接內(nèi)存進(jìn)行Socket讀寫,數(shù)據(jù)傳輸時(shí)無需經(jīng)過二次拷貝。如果使用傳統(tǒng)的堆內(nèi)存進(jìn)行Socket網(wǎng)絡(luò)數(shù)據(jù)讀寫,JVM需要先將堆內(nèi)存中的數(shù)據(jù)拷貝一份到直接內(nèi)存,然后才寫入Socket緩沖區(qū)中,相較于堆外直接內(nèi)存,消息在發(fā)送過程中多了一次緩沖區(qū)的內(nèi)存拷貝。

2)Netty的文件傳輸采用了transferTo()/transferFrom()方法,它可以直接將文件緩沖區(qū)的數(shù)據(jù)發(fā)送到目標(biāo)Channel(Socket),底層就是調(diào)用了sendfile()內(nèi)核函數(shù),避免了文件數(shù)據(jù)的CPU拷貝過程。

3)Netty提供了組合、拆解ByteBuf對(duì)象的API,咱們可以基于一個(gè)ByteBuf對(duì)象,對(duì)數(shù)據(jù)進(jìn)行拆解,也可以基于多個(gè)ByteBuf對(duì)象進(jìn)行數(shù)據(jù)合并,這個(gè)過程中不會(huì)出現(xiàn)數(shù)據(jù)拷貝,這個(gè)是程序級(jí)別的零拷貝,實(shí)際上就是在原數(shù)據(jù)的基礎(chǔ)上用不同的引用表示而已。

2. 其他技術(shù)中的零拷貝技術(shù)應(yīng)用

Kafka底層基于java.nio包下的FileChannel.transferTo()實(shí)現(xiàn)零拷貝。Kafka Server基于FileChannel將文件中的消息數(shù)據(jù)發(fā)送到SocketChannel。

RocketMQ基于mmap + write的方式實(shí)現(xiàn)零拷貝。內(nèi)部實(shí)現(xiàn)基于nio提供的java.nio.MappedByteBuffer,基于FileChannel的map方法得到mmap的緩沖區(qū)。

分享到:
標(biāo)簽:拷貝
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定