深刻淺出計算機組成原理學習筆記:第四十八講

1、引子

過去幾年裏,整個計算機產業屆,都在嘗試不停地提高I/O設備的速度。把HDD硬盤換成SSD硬盤,咱們仍然以爲不夠快;用PCI Express接口的SSD硬盤替代SATA接口的SSD硬盤,
咱們仍是以爲不夠快,因此,如今就有了傲騰(Optane)這樣的技術。java

可是,不管I/O速度如何提高,比起CPU,總仍是太慢。SSD硬盤的IOPS能夠到2萬、4萬,可是咱們CPU的主頻有2GHz以上,也就意味着每秒會有20億次的操做。網絡

若是咱們對於I/O的操做,都是由CPU發出對應的指令,而後等待I/O設備完成操做以後返回,那CPU有大量的時間其實都是在等待I/O設備完成操做。socket

可是,這個CPU的等待,在不少時候,其實並無太多的實際意義。咱們對於I/O設備的⼤量操做,其實都只是把內存裏面的數據,傳輸到I/O設備而已。
在這種狀況下,其實CPU只是在傻等而已。特別是當傳輸的ide

所以,計算機工程師們,就發明了DMA技術,也就是 直接內存訪問(Direct Memory Access)技術,來減小CPU等待的時間。

性能

二 、理解DMA,一個協處理器

一、什麼是DMA?測試

其實DMA技術很容易理解,本質上,DMA技術就是咱們在主板上放⼀塊獨立的芯片。在進行內存和I/O設備的數據傳輸的時候,咱們再也不經過CPU來控制數據傳輸,
而直接經過 DMA控制器(DMA?Controller,簡稱DMAC)。這塊芯片,咱們能夠認爲它其實就是一個協處理器(Co-Processor)spa

二、DMAC最有價值的地方體如今那?操作系統

當咱們要傳輸的數據特別大、速度特別快,或者傳輸的數據特別小、速度特別慢的時候日誌

好比說,咱們的千兆網卡或者硬盤傳輸大量數據的時候,若是都用CPU來搬運的話,確定忙不過來,因此能夠選擇DMAC。而當數據傳輸很慢的時候,
DMAC能夠等數據到齊了,再發送信號,給到CPU去處理,而不是讓CPU在那裏忙等待。blog

三、DMAC是一塊「協處理器芯片」,這是爲何呢?

注意,這裏的「協」字。DMAC是在「協助」CPU,完成對應的數據傳輸⼯做。在DMAC控制數據傳輸的過程當中,咱們仍是須要CPU的。

四、總線上的設備、分爲那兩種類型?

除此以外,DMAC其實也是一個特殊的I/O設備,它和CPU以及其餘I/O設備⼀樣,經過鏈接到總線來進行實際的數據傳輸。總線上的設備呢,
其實有兩種類型。一種咱們稱之爲 主設備(Master),另一種,咱們稱之爲 從設備(Slave)。

五、想要主動發起數據傳輸,必需要是一個主設備才能夠?

想要主動發起數據傳輸,必需要是一個主設備才能夠,CPU就是主設備。而咱們從設備(好比硬盤)只能接受數據傳輸。因此,若是經過CPU來傳輸數據,
要麼是CPU從I/O設備讀數據,要麼是CPU向I/O設備寫數據。

這個時候你可能要問了,那咱們的I/O設備不能向主設備發起請求麼?能夠是能夠,不過這個發送的不是數據內容,而是控制信號。
I/O設備能夠告訴CPU,我這裏有數據要傳輸給你,可是實際數據是CPU從拉取的,而不是I/O設備推給CPU的

六、DMAC既是一個主設備,又是一個從設備

不過,DMAC就頗有意思了,它既是一個主設備,又是一個從設備。對於CPU來講,它是一個從設備;對於硬盤這樣的IO設備來講呢,它又變成了一個主設備。

七、使用DMAC進行數據傳輸的過程到底是什麼樣的呢?

1.首先,CPU仍是做爲一個主設備,向DMAC設備發起請求。這個請求,其實就是在DMAC裏面修改配置寄存器。

2.CPU修改DMAC的配置的時候,會告訴DMAC這樣幾個信息:

3.設置完這些信息以後,DMAC就會變成一個空閒的狀態(Idle)。

4.若是咱們要從硬盤上往內存裏面加載數據,這個時候,硬盤就會向DMAC發起⼀個數據傳輸請求。這個請求並非經過總線,而是經過一個額外的連線。

5.而後,咱們的DMAC須要再經過一個額外的連線響應這個申請。

6.因而,DMAC這個芯片,就向硬盤的接口發起要總線讀的傳輸請求。數據就從硬盤裏面,讀到了DMAC的控制器裏面。

7.而後,DMAC再向咱們的內存發起總線寫的數據傳輸請求,把數據寫⼊到內存⾥⾯。
8.DMAC會反覆進行上面第六、7步的操做,直到DMAC的寄存器裏面設置的數據長度傳輸完成。
9.數據傳輸完成以後,DMAC從新回到第3步的空閒狀態。

因此,整個數據傳輸的過程當中,咱們不是經過CPU來搬運數據,而是由DMAC這個芯⽚來搬運數據。可是CPU在這個過程當中也是必不可少的。由於傳輸什麼數據,
從哪裏傳輸到哪裏,其實仍是由CPU來設置的。這也是爲何,DMAC被叫做「協處理器」。

最先,計算機裏是沒有DMAC的,全部數據都是由CPU來搬運的。隨着對於數據傳輸的需求愈來愈多,先是出現了主板上獨立的DMAC控制器。到了今天,各類I/O設備愈來愈多,
數據傳輸的需求愈來愈複雜,使用的場景各不相同。加之顯示器、網卡、硬盤對於數據傳輸的需求都不同,因此各個設備裏面都有本身的DMAC芯片了。

3、爲何那麼快?一塊兒來看Kafka的實現原理

一、它到底是怎麼利用DMA的?

Kafka是一個用來處理實時數據的管道,咱們經常用它來作一個消息隊列,或者用來收集和落地海量的日誌。做爲一個處理實時數據和日誌的管道,瓶頸天然也在I/O層面。

二、Kafka裏面兩種經常使用的海量數據傳輸的狀況是什麼?

Kafka裏面會有兩種經常使用的海量數據傳輸的狀況。一種是從網絡絡中接收上游的數據,而後須要落地到本地的磁盤上,確保數據不丟失。
另外一種狀況呢,則是從本地磁盤上讀取出來,經過網絡發送出去。

咱們來看一看後一種狀況,從磁盤讀數據發送到網絡上去。若是咱們本身寫一個簡單的程序,最直觀的辦法,天然是用個一件讀操做,從磁盤上把數據讀到內存裏面來,
而後再用個Socket,把這些數據發送到網絡上去。

File.read(fileDesc, buf, len);
Socket.send(socket, buf, len);

三、咱們只是要「搬運」一份數據,結果卻整整搬運了四次

在這個過程當中,數據一共發生了四次傳輸的過程。其中兩次是DMA的傳輸,另外兩次,則是經過CPU控制的傳輸。下面咱們來具體看看這個過程。

第一次傳輸,是從硬盤上,讀到操做系統內核的緩衝區裏。這個傳輸是經過DMA搬運的。

第二次傳輸,須要從內核緩衝區裏面的數據,複製到咱們應用分配的內存裏面。這個傳輸是經過CPU搬運的。

第三次傳輸,要從咱們應用的內存裏面,再寫到操做系統的Socket的緩衝區裏面去。這個傳輸,仍是由CPU搬運的。

最後一次傳輸,須要再從Socket的緩衝區裏面,寫到網卡的緩衝區裏面去。這個傳輸又是經過DMA搬運的。

 


這個時候,你能夠回過頭看看這個過程。咱們只是要「搬運」⼀份數據,結果卻整整搬運了四次。並且這裏面,從內核的讀緩衝區傳輸到應用的內存裏,
再從應用的內存裏傳輸到Socket的緩衝區裏,其實都是把同一份數據在內存裏面搬運來搬運去,特別沒有效率。

四、咱們就須要儘量地減小數據搬運的需求

像Kafka這樣的應用場景,其實一部分最終利用到的硬件資源,其實又都是在幹這個搬運數據的事兒。因此,咱們就須要儘量地減小數據搬運的需求。

事實上,Kafka作的事情就是,把這個數據搬運的次數,從上面的四次,變成了兩次,而且只有DMA來進行數據搬運,而不須要CPU。

@Override
public long transferFrom(FileChannel fileChannel, long position, long count) throws IOException {
    return fileChannel.transferTo(position, count, socketChannel);
}

Kafka的代碼調用了Java NIO庫,具體是FileChannel裏面的transferTo方法。咱們的數據並無讀到中間的應用內存裏面,而是直接經過Channel,寫入到對應的網絡設備裏。
而且,對於Socket的操做,也不是寫入到Socket的Buffer裏面,而是直接根據描述符(Descriptor)寫到到網卡的緩衝區裏面。因而,在這個過程之中,咱們只進行了兩次數據傳輸。

五、同一份數據傳輸的次數從四次變成了兩次

 

第一次,是經過DMA,從硬盤直接讀到操做系統內核的讀緩衝區裏面。第二次,則是根據Socket的描述符信息,直接從讀緩衝區裏面,寫入到網卡的緩衝區裏面。

這樣,咱們同一份數據傳輸的次數從四次變成了兩次,而且沒有經過CPU來進行數據搬運,全部的數據都是經過DMA來進行傳輸的。

六、什麼是零拷貝?

在這個方法裏面,咱們沒有在內存層面去「複製(Copy)」數據,因此這個方法,也被稱之爲零拷貝(Zero-Copy)。IBM Developer Works裏面有一篇文章,專們寫過程序來測試過在一樣的硬件下,使用零拷貝可以帶來的性能提高。我在這裏放上這篇文章連接。在這篇文章最後,你能夠看到,不管傳輸數據量的大小,傳輸一樣的數據,使用了零拷貝可以縮短65%的時間,大幅度提高了機器傳輸數據的吞吐量。想要深刻了解零拷貝,建議你能夠仔細讀讀讀這篇文章。

 4、總結延伸

講到這裏,相信你對DMA的原理、做用和效果都有所理解了。那麼,咱們⼀起來回顧總結一下。、

若是咱們始終讓CPU來進行各類數據傳輸工做,會特別浪費。一方面,咱們的數據傳輸工做用不到多少CPU核新的「計算」功能。另外一方面,CPU的運轉速度也比I/O操做要快不少。
因此,咱們但願可以給CPU「減負」。

因而,工程師們就在主板上放上了DMAC這樣一個協處理器芯片。經過這個芯片,CPU只須要告訴DMAC,咱們要傳輸什麼數據,從哪裏來,到哪裏去,就能夠放心離開了。

後續的實際數據傳輸工做,都會有DMAC來完成。隨着現代計算機各類外設硬件愈來愈多,光一個通用的DMAC芯片不夠了,咱們在各個外設上都加上了DMAC芯片,

使得CPU不多再須要關注數據傳輸的工做了。

在咱們實際的系統開發過程當中,利用好DMA的數據傳輸機制,也能夠大幅提高I/O的吞吐率。最典型的例子就是Kafka。

傳統地從硬盤讀取數據,而後再經過網卡上向外發送,咱們須要進行四次數據傳輸,其中有兩次是發生在內存裏的緩衝區和對應的硬件設備之間,咱們無法節省掉。
可是還有兩次,徹底是經過CPU在內存裏面進行數據複製。

在Kafka裏,經過Java的NIO裏面FileChannel的transferTo方法調用,咱們能夠不用把數據複製到咱們應用程序的內存裏面。經過DMA的方式,
咱們能夠把數據從內存緩衝區直接寫到網卡的緩衝區裏面。在使用了這樣的零拷貝的方法以後呢,咱們傳輸一樣數據的時間,能夠縮減爲原來的1/3,至關於提高了3倍的吞吐率。

這也是爲何,Kafka是目前實時數據傳輸管道的標準解決方案

相關文章
相關標籤/搜索