1. 淺析操作系統(tǒng)和Netty中的零拷貝機(jī)制

        共 2779字,需瀏覽 6分鐘

         ·

        2020-12-04 18:51

        點(diǎn)擊上方「藍(lán)字」關(guān)注我們


        零拷貝機(jī)制(Zero-Copy)是在操作數(shù)據(jù)時(shí)不需要將數(shù)據(jù)從一塊內(nèi)存區(qū)域復(fù)制到另一塊內(nèi)存區(qū)域的技術(shù),這樣就避免了內(nèi)存的拷貝,使得可以提高CPU的。零拷貝機(jī)制是一種操作數(shù)據(jù)的優(yōu)化方案,通過避免數(shù)據(jù)在內(nèi)存中拷貝達(dá)到的提高CPU性能的方案。


        一、操作系統(tǒng)的零拷貝機(jī)制

        操作系統(tǒng)的存儲空間包含硬盤和內(nèi)存,而內(nèi)存又分成用戶空間和內(nèi)核空間。以從文件服務(wù)器下載文件為例,服務(wù)器需要將硬盤中的數(shù)據(jù)通過網(wǎng)絡(luò)通信發(fā)送給客戶端,大致流程如下:

        1. 操作系統(tǒng)通過DMA傳輸將硬盤中的數(shù)據(jù)復(fù)制到內(nèi)核緩沖區(qū)

        2. 操作系統(tǒng)執(zhí)行read方法將內(nèi)核緩沖區(qū)的數(shù)據(jù)復(fù)制到用戶空間

        3. 操作系統(tǒng)執(zhí)行write方法將用戶空間的數(shù)據(jù)復(fù)制到內(nèi)核socket緩沖區(qū)

        4. 操作系統(tǒng)通過DMA傳輸將內(nèi)核socket緩沖區(qū)數(shù)據(jù)復(fù)制給網(wǎng)卡發(fā)送數(shù)據(jù)

        流程如下圖示:

        整個(gè)流程中:DMA拷貝2次、CPU拷貝2次、用戶空間和內(nèi)核空間切換4次

        整個(gè)流程從內(nèi)核空間和硬件之間數(shù)據(jù)拷貝是DMA復(fù)制傳輸,內(nèi)核空間和用戶空間之間數(shù)據(jù)拷貝是通過CPU復(fù)制.另外CPU除了需要參與拷貝任務(wù),還需要多次從內(nèi)核空間和用戶空間之間來回切換,無疑都額外增加了很多的CPU工作負(fù)擔(dān)。

        所以操作系統(tǒng)為了減少CPU拷貝數(shù)據(jù)帶來的性能消耗,提供了幾種解決方案來減少CPU拷貝次數(shù)


        1.1、使用mmap函數(shù)

        mmap函數(shù)的作用相當(dāng)于是內(nèi)存共享,將內(nèi)核空間的內(nèi)存區(qū)域和用戶空間共享,這樣就避免了將內(nèi)核空間的數(shù)據(jù)拷貝到用戶空間的步驟,通過mmap函數(shù)發(fā)送數(shù)據(jù)時(shí)上述的步驟如下:

        1. 操作系統(tǒng)通過DMA傳輸將硬盤中的數(shù)據(jù)復(fù)制到內(nèi)核緩沖區(qū),執(zhí)行了mmap函數(shù)之后,拷貝到內(nèi)核緩沖區(qū)的數(shù)據(jù)會和用戶空間進(jìn)行共享,所以不需要進(jìn)行拷貝

        2. CPU將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到內(nèi)核空間socket緩沖區(qū)

        3. 操作系統(tǒng)通過DMA傳輸將內(nèi)核socket緩沖區(qū)數(shù)據(jù)拷貝給網(wǎng)卡發(fā)送數(shù)據(jù)

        流程如下圖示:

        整個(gè)流程中:DMA拷貝2次、CPU拷貝1次、用戶空間和內(nèi)核空間切換4次

        可以發(fā)現(xiàn)此種方案避免了內(nèi)核空間和用戶空間之間數(shù)據(jù)的拷貝工作,但是在內(nèi)核空間內(nèi)部還是會有一次數(shù)據(jù)拷貝過程,而且CPU還是會有從內(nèi)核空間和用戶空間的切換過程


        1.2、使用sendfile函數(shù)

        senfile函數(shù)的作用是將一個(gè)文件描述符的內(nèi)容發(fā)送給另一個(gè)文件描述符。而用戶空間是不需要關(guān)心文件描述符的,所以整個(gè)的拷貝過程只會在內(nèi)核空間操作,相當(dāng)于減少了內(nèi)核空間和用戶空間之間數(shù)據(jù)的拷貝過程,而且還避免了CPU在內(nèi)核空間和用戶空間之間的來回切換過程。整體流程如下:

        1. 通過DMA傳輸將硬盤中的數(shù)據(jù)復(fù)制到內(nèi)核頁緩沖區(qū)

        2. 通過sendfile函數(shù)將頁緩沖區(qū)的數(shù)據(jù)通過CPU拷貝給socket緩沖區(qū)

        3. 網(wǎng)卡通過DMA傳輸將socket緩沖區(qū)的數(shù)據(jù)拷貝走并發(fā)送數(shù)據(jù)

        流程如下圖示:


        整個(gè)過程中:DMA拷貝2次、CPU拷貝1次、內(nèi)核空間和用戶空間切換0次

        可以看出通過sendfile函數(shù)時(shí)只會有一次CPU拷貝過程,而且全程都是在內(nèi)核空間實(shí)現(xiàn)的,所以整個(gè)過程都不會使得CPU在內(nèi)核空間和用戶空間進(jìn)行來回切換的操作,性能相比于mmap而言要更好

        另外如果硬件支持的話,sendfile函數(shù)還可以直接將文件描述符和數(shù)據(jù)長度發(fā)送給socket緩沖區(qū),然后直接通過DMA傳輸將頁緩沖區(qū)的數(shù)據(jù)拷貝給網(wǎng)卡進(jìn)行發(fā)送即可,這樣就避免了CPU在內(nèi)核空間內(nèi)的拷貝過程,流程如下:

        1. 通過DMA傳輸將硬盤中的數(shù)據(jù)復(fù)制到內(nèi)核頁緩沖區(qū)

        2. 通過sendfile函數(shù)將頁緩沖區(qū)數(shù)據(jù)的文件描述符和數(shù)據(jù)長度發(fā)送給socket緩沖區(qū)

        3. 網(wǎng)卡通過DMA傳輸根據(jù)文件描述符和文件長度直接從頁緩沖區(qū)拷貝數(shù)據(jù)

        如下圖示:

        整個(gè)過程中:DMA拷貝2次、CPU拷貝0次、內(nèi)核空間和用戶空間切換0次

        所以整個(gè)過程都是沒有CPU拷貝的過程的,實(shí)現(xiàn)了真正的CPU零拷貝機(jī)制


        1.3、使用slice函數(shù)

        splice函數(shù)的作用是將兩個(gè)文件描述符之間建立一個(gè)管道,然后將文件描述符的引用傳遞過去,這樣在使用到數(shù)據(jù)的時(shí)候就可以直接通過引用指針訪問到具體數(shù)據(jù)。過程如下:

        1. 通過DMA傳輸將文件復(fù)制到內(nèi)核頁緩沖區(qū)

        2. 通過splice函數(shù)在頁緩沖區(qū)和socket緩沖區(qū)之間建立管道,并將文件描述符的引用指針發(fā)送給socket緩沖區(qū)

        3. 網(wǎng)卡通過DMA傳輸根據(jù)文件描述符的指針直接訪問數(shù)據(jù)

        如下圖示:

        整個(gè)過程中:DMA拷貝2次、CPU拷貝0次、內(nèi)核空間和用戶空間切換0次

        可以看出通過slice函數(shù)傳輸數(shù)據(jù)時(shí)同樣可以實(shí)現(xiàn)CPU的零拷貝,且不需要CPU在內(nèi)核空間和用戶空間之間來回切換


        總結(jié):實(shí)際上操作系統(tǒng)的零拷貝機(jī)制只是針對于CPU的零拷貝,而內(nèi)核空間和硬件之間還是會存在數(shù)據(jù)拷貝的過程,只不過通過DMA傳輸,而不需要CPU來參與數(shù)據(jù)的拷貝過程可以看出通過mmap函數(shù)可以減少一次CPU拷貝,但是還會有一個(gè)CPU拷貝。而使用sendfile和splice函數(shù)都已經(jīng)實(shí)現(xiàn)了CPU零拷貝而實(shí)現(xiàn)了數(shù)據(jù)傳輸過程。


        二、Java中的零拷貝機(jī)制

        Java的應(yīng)用程序經(jīng)常會遇到數(shù)據(jù)傳輸?shù)膱鼍?在Java NIO包中就提供了零拷貝機(jī)制的實(shí)現(xiàn),主要是通過NIO包中的FileChannel實(shí)現(xiàn)FileChannel提供了transferTo和transferFrom方法,都是采用了調(diào)用底層操作系統(tǒng)的sendfile函數(shù)來實(shí)現(xiàn)的CPU零拷貝機(jī)制。

        kafka服務(wù)器就是采用了FileChannel的transfer方法實(shí)現(xiàn)了高性能的IO傳輸操作

        Netty中的零拷貝機(jī)制Netty作為NIO的高性能網(wǎng)絡(luò)通信框架,同樣也實(shí)現(xiàn)了零拷貝機(jī)制,不過和操作系統(tǒng)的零拷貝機(jī)制則不是一個(gè)概念

        Netty中的零拷貝機(jī)制體現(xiàn)在多個(gè)場景:

        1. 使用直接內(nèi)存,在進(jìn)行IO數(shù)據(jù)傳輸時(shí)避免了ByteBuf從堆外內(nèi)存拷貝到堆內(nèi)內(nèi)存的步驟,而如果使用堆內(nèi)內(nèi)存分配ByteBuf的話,那么發(fā)送數(shù)據(jù)時(shí)需要將IO數(shù)據(jù)從堆內(nèi)內(nèi)存拷貝到堆外內(nèi)存才能通過Socket發(fā)送

        2. Netty的文件傳輸使用了FileChannel的transferTo方法,底層使用到sendfile函數(shù)來實(shí)現(xiàn)了CPU零拷貝

        3. Netty中提供CompositeByteBuf類,用于將多個(gè)ByteBuf合并成邏輯上的ByteBuf,避免了將多個(gè)ByteBuf拷貝成一個(gè)ByteBuf的過程

        4. ByteBuf支持slice方法可以將ByteBuf分解成多個(gè)共享內(nèi)存區(qū)域的ByteBuf,避免了內(nèi)存拷貝

        source:https://www.cnblogs.com/jackion5/p/13604331.html

        掃碼二維碼

        獲取更多精彩

        Java樂園

        有用!分享+在看?
        瀏覽 53
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 老熟女亂伦一区二区三区视频观看 | 欧美三级大片在线观看 | 一级片在哪里看 | 午夜伦情电午夜伦情电影8090 | 欧美年龄大点女人做爱视频免费看 |