续说零拷贝(Zero-Copy) - DMA技术
如果想理解Kafaka為什么這么快,得先看DMA是什么.
DMA:
????? 無論 I/O 速度如何提升,比起 CPU,總還是太慢。SSD 硬盤的 IOPS 可以到 2 萬、4 萬,但是我們 CPU 的主頻有 2GHz 以上,也就意味著每秒會有 20 億次的操作.
如果我們對于 I/O 的操作,都是由 CPU 發(fā)出對應(yīng)的指令,然后等待 I/O 設(shè)備完成操作之后返回,那 CPU 有大量的時間其實都是在等待 I/O 設(shè)備完成操作。
但是,這個 CPU 的等待,在很多時候,其實并沒有太多的實際意義。我們對于 I/O 設(shè)備的大量操作,其實都只是把內(nèi)存里面的數(shù)據(jù),傳輸?shù)?I/O 設(shè)備而已。在這種情況下,其實 CPU 只是在傻等而已。特別是當(dāng)傳輸?shù)臄?shù)據(jù)量比較大的時候,比如進(jìn)行大文件復(fù)制,如果所有數(shù)據(jù)都要經(jīng)過 CPU,實在是有點(diǎn)兒太浪費(fèi)時間了。
因此,計算機(jī)工程師們,就發(fā)明了 DMA 技術(shù),也就是直接內(nèi)存訪問(Direct Memory Access)技術(shù),來減少 CPU 等待的時間。
?
理解 DMA,一個協(xié)處理器:
其實 DMA 技術(shù)很容易理解,本質(zhì)上,DMA 技術(shù)就是我們在主板上放一塊獨(dú)立的芯片。在進(jìn)行內(nèi)存和 I/O 設(shè)備的數(shù)據(jù)傳輸?shù)臅r候,我們不再通過 CPU 來控制數(shù)據(jù)傳輸,而直接通過DMA 控制器(DMA Controller,簡稱 DMAC)。這塊芯片,我們可以認(rèn)為它其實就是一個協(xié)處理器(Co-Processor)。
DMAC 最有價值的地方體現(xiàn)在,當(dāng)我們要傳輸?shù)臄?shù)據(jù)特別大、速度特別快,或者傳輸?shù)臄?shù)據(jù)特別小、速度特別慢的時候。
比如說,我們用千兆網(wǎng)卡或者硬盤傳輸大量數(shù)據(jù)的時候,如果都用 CPU 來搬運(yùn)的話,肯定忙不過來,所以可以選擇 DMAC。而當(dāng)數(shù)據(jù)傳輸很慢的時候,DMAC 可以等數(shù)據(jù)到齊了,再發(fā)送信號,給到 CPU 去處理,而不是讓 CPU 在那里忙等待。
?DMAC數(shù)據(jù)傳輸?shù)倪^程:
?
1. 首先,CPU 還是作為一個主設(shè)備,向 DMAC 設(shè)備發(fā)起請求。這個請求,其實就是在 DMAC 里面修改配置寄存器。
2.CPU 修改 DMAC 的配置的時候,會告訴 DMAC 這樣幾個信息:
- 首先是源地址的初始值以及傳輸時候的地址增減方式。
 所謂源地址,就是數(shù)據(jù)要從哪里傳輸過來。如果我們要從內(nèi)存里面寫入數(shù)據(jù)到硬盤上,那么就是要讀取的數(shù)據(jù)在內(nèi)存里面的地址。如果是從硬盤讀取數(shù)據(jù)到內(nèi)存里,那就是硬盤的 I/O 接口的地址。
 我們講過總線的時候說過,I/O 的地址可以是一個內(nèi)存地址,也可以是一個端口地址。而地址的增減方式就是說,數(shù)據(jù)是從大的地址向小的地址傳輸,還是從小的地址往大的地址傳輸。
- 其次是目標(biāo)地址初始值和傳輸時候的地址增減方式。目標(biāo)地址自然就是和源地址對應(yīng)的設(shè)備,也就是我們數(shù)據(jù)傳輸?shù)哪康牡亍?/li>
- 第三個自然是要傳輸?shù)臄?shù)據(jù)長度,也就是我們一共要傳輸多少數(shù)據(jù)。
3. 設(shè)置完這些信息之后,DMAC 就會變成一個空閑的狀態(tài)(Idle)。
4. 如果我們要從硬盤上往內(nèi)存里面加載數(shù)據(jù),這個時候,硬盤就會向 DMAC 發(fā)起一個數(shù)據(jù)傳輸請求。這個請求并不是通過總線,而是通過一個額外的連線。
5. 然后,我們的 DMAC 需要再通過一個額外的連線響應(yīng)這個申請。
6. 于是,DMAC 這個芯片,就向硬盤的接口發(fā)起要總線讀的傳輸請求。數(shù)據(jù)就從硬盤里面,讀到了 DMAC 的控制器里面。
7. 然后,DMAC 再向我們的內(nèi)存發(fā)起總線寫的數(shù)據(jù)傳輸請求,把數(shù)據(jù)寫入到內(nèi)存里面。
8.DMAC 會反復(fù)進(jìn)行上面第 6、7 步的操作,直到 DMAC 的寄存器里面設(shè)置的數(shù)據(jù)長度傳輸完成。
9. 數(shù)據(jù)傳輸完成之后,DMAC 重新回到第 3 步的空閑狀態(tài)。
所以,整個數(shù)據(jù)傳輸?shù)倪^程中,我們不是通過 CPU 來搬運(yùn)數(shù)據(jù),而是由 DMAC 這個芯片來搬運(yùn)數(shù)據(jù)。但是 CPU 在這個過程中也是必不可少的。因為傳輸什么數(shù)據(jù),從哪里傳輸?shù)侥睦?#xff0c;其實還是由 CPU 來設(shè)置的。
為什么那么快?一起來看 Kafka 的實現(xiàn)原理
Kafka 是一個用來處理實時數(shù)據(jù)的管道,我們常常用它來做一個消息隊列,或者用來收集和落地海量的日志。作為一個處理實時數(shù)據(jù)和日志的管道,瓶頸自然也在 I/O 層面。
從磁盤讀數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上去,數(shù)據(jù)一共發(fā)生了四次傳輸?shù)倪^程。其中兩次是 DMA 的傳輸,另外兩次,則是通過 CPU 控制的傳輸:
?
第一次傳輸,是從硬盤上,讀到操作系統(tǒng)內(nèi)核的緩沖區(qū)里。這個傳輸是通過 DMA 搬運(yùn)的。
第二次傳輸,需要從內(nèi)核緩沖區(qū)里面的數(shù)據(jù),復(fù)制到我們應(yīng)用分配的內(nèi)存里面。這個傳輸是通過 CPU 搬運(yùn)的。
第三次傳輸,要從我們應(yīng)用的內(nèi)存里面,再寫到操作系統(tǒng)的 Socket 的緩沖區(qū)里面去。這個傳輸,還是由 CPU 搬運(yùn)的。
最后一次傳輸,需要再從 Socket 的緩沖區(qū)里面,寫到網(wǎng)卡的緩沖區(qū)里面去。這個傳輸又是通過 DMA 搬運(yùn)的。
像 Kafka 這樣的應(yīng)用場景,其實大部分最終利用到的硬件資源,其實又都是在干這個搬運(yùn)數(shù)據(jù)的事兒。所以,我們就需要盡可能地減少數(shù)據(jù)搬運(yùn)的需求。
事實上,Kafka 做的事情就是,把這個數(shù)據(jù)搬運(yùn)的次數(shù),從上面的四次,變成了兩次,并且只有 DMA 來進(jìn)行數(shù)據(jù)搬運(yùn),而不需要 CPU。
Kafka 的代碼調(diào)用了 Java NIO 庫,具體是 FileChannel 里面的 transferTo 方法。我們的數(shù)據(jù)并沒有讀到中間的應(yīng)用內(nèi)存里面,而是直接通過 Channel,寫入到對應(yīng)的網(wǎng)絡(luò)設(shè)備里。并且,對于 Socket 的操作,也不是寫入到 Socket 的 Buffer 里面,而是直接根據(jù)描述符(Descriptor)寫入到網(wǎng)卡的緩沖區(qū)里面。于是,在這個過程之中,我們只進(jìn)行了兩次數(shù)據(jù)傳輸。
第一次,是通過 DMA,從硬盤直接讀到操作系統(tǒng)內(nèi)核的讀緩沖區(qū)里面。第二次,則是根據(jù) Socket 的描述符信息,直接從讀緩沖區(qū)里面,寫入到網(wǎng)卡的緩沖區(qū)里面。
這樣,我們同一份數(shù)據(jù)傳輸?shù)拇螖?shù)從四次變成了兩次,并且沒有通過 CPU 來進(jìn)行數(shù)據(jù)搬運(yùn),所有的數(shù)據(jù)都是通過 DMA 來進(jìn)行傳輸?shù)摹?/p>
在這個方法里面,我們沒有在內(nèi)存層面去“復(fù)制(Copy)”數(shù)據(jù),所以這個方法,也被稱之為零拷貝(Zero-Copy)。無論傳輸數(shù)據(jù)量的大小,傳輸同樣的數(shù)據(jù),使用了零拷貝能夠縮短 65% 的時間,大幅度提升了機(jī)器傳輸數(shù)據(jù)的吞吐量。
在 Kafka 里,通過 Java 的 NIO 里面 FileChannel 的 transferTo 方法調(diào)用,我們可以不用把數(shù)據(jù)復(fù)制到我們應(yīng)用程序的內(nèi)存里面。通過 DMA 的方式,我們可以把數(shù)據(jù)從內(nèi)存緩沖區(qū)直接寫到網(wǎng)卡的緩沖區(qū)里面。在使用了這樣的零拷貝的方法之后呢,我們傳輸同樣數(shù)據(jù)的時間,可以縮減為原來的 1/3,相當(dāng)于提升了 3 倍的吞吐率。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的续说零拷贝(Zero-Copy) - DMA技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: kafka架构、亿级数据如何优化GC
- 下一篇: 轻松使用zstd来解压缩
