0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一般會(huì)如何實(shí)現(xiàn)文件傳輸?零拷貝如何提升文件傳輸性能?

馬哥Linux運(yùn)維 ? 來(lái)源:-零 ? 2023-07-26 14:43 ? 次閱讀

一般會(huì)如何實(shí)現(xiàn)文件傳輸?

服務(wù)器提供文件傳輸功能,需要將磁盤上的文件讀取出來(lái),通過(guò)網(wǎng)絡(luò)協(xié)議發(fā)送到客戶端。如果需要你自己編碼實(shí)現(xiàn)這個(gè)文件傳輸功能,你會(huì)怎么實(shí)現(xiàn)呢?

通常,你會(huì)選擇最直接的方法:從網(wǎng)絡(luò)請(qǐng)求中找出文件在磁盤中的路徑后,如果這個(gè)文件比較大,假設(shè)有 320MB,可以在內(nèi)存中分配 32KB 的緩沖區(qū),再把文件分成一萬(wàn)份,每份只有 32KB,這樣,從文件的起始位置讀入 32KB 到緩沖區(qū),再通過(guò)網(wǎng)絡(luò) API 把這 32KB 發(fā)送到客戶端。接著重復(fù)一萬(wàn)次,直到把完整的文件都發(fā)送完畢。如下圖所示:

31d4e830-29ef-11ee-a368-dac502259ad0.png

不過(guò)這個(gè)方案性能并不好,主要有兩個(gè)原因。

上下文切換:

首先,它至少經(jīng)歷了 4 萬(wàn)次用戶態(tài)與內(nèi)核態(tài)的上下文切換。因?yàn)槊刻幚?32KB 的消息,就需要一次 read 調(diào)用和一次 write 調(diào)用,每次系統(tǒng)調(diào)用都得先從用戶態(tài)切換到內(nèi)核態(tài),等內(nèi)核完成任務(wù)后,再?gòu)膬?nèi)核態(tài)切換回用戶態(tài)??梢?,每處理 32KB,就有 4 次上下文切換,重復(fù) 1 萬(wàn)次后就有 4 萬(wàn)次切換。

上下文切換的成本并不小,雖然一次切換僅消耗幾十納秒到幾微秒,但高并發(fā)服務(wù)會(huì)放大這類時(shí)間的消耗。

內(nèi)存拷貝:

其次,這個(gè)方案做了 4 萬(wàn)次內(nèi)存拷貝,對(duì) 320MB 文件拷貝的字節(jié)數(shù)也翻了 4 倍,到了 1280MB。很顯然,過(guò)多的內(nèi)存拷貝無(wú)謂地消耗了 CPU 資源,降低了系統(tǒng)的并發(fā)處理能力。

所以要想提升傳輸文件的性能,需要從降低上下文切換的頻率和內(nèi)存拷貝次數(shù)兩個(gè)方向入手。

零拷貝如何提升文件傳輸性能?

首先,我們來(lái)看如何降低上下文切換的頻率。

為什么讀取磁盤文件時(shí),一定要做上下文切換呢?這是因?yàn)?,讀取磁盤或者操作網(wǎng)卡都由操作系統(tǒng)內(nèi)核完成。內(nèi)核負(fù)責(zé)管理系統(tǒng)上的所有進(jìn)程,它的權(quán)限最高,工作環(huán)境與用戶進(jìn)程完全不同。只要我們的代碼執(zhí)行 read 或者 write 這樣的系統(tǒng)調(diào)用,一定會(huì)發(fā)生 2 次上下文切換:首先從用戶態(tài)切換到內(nèi)核態(tài),當(dāng)內(nèi)核執(zhí)行完任務(wù)后,再切換回用戶態(tài)交由進(jìn)程代碼執(zhí)行。

因此,如果想減少上下文切換次數(shù),就一定要減少系統(tǒng)調(diào)用的次數(shù)。解決方案就是把 read、write 兩次系統(tǒng)調(diào)用合并成一次,在內(nèi)核中完成磁盤與網(wǎng)卡的數(shù)據(jù)交換。

其次,我們應(yīng)該考慮如何減少內(nèi)存拷貝次數(shù)。

每周期中的 4 次內(nèi)存拷貝,其中與物理設(shè)備相關(guān)的 2 次拷貝是必不可少的,包括:把磁盤內(nèi)容拷貝到內(nèi)存,以及把內(nèi)存拷貝到網(wǎng)卡。但另外 2 次與用戶緩沖區(qū)相關(guān)的拷貝動(dòng)作都不是必需的,因?yàn)樵诎汛疟P文件發(fā)到網(wǎng)絡(luò)的場(chǎng)景中,用戶緩沖區(qū)沒(méi)有必須存在的理由。

如果內(nèi)核在讀取文件后,直接把 PageCache 中的內(nèi)容拷貝到 Socket 緩沖區(qū),待到網(wǎng)卡發(fā)送完畢后,再通知進(jìn)程,這樣就只有 2 次上下文切換,和 3 次內(nèi)存拷貝。

31e0706a-29ef-11ee-a368-dac502259ad0.jpg

如果網(wǎng)卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技術(shù),還可以再去除 Socket 緩沖區(qū)的拷貝,這樣一共只有 2 次內(nèi)存拷貝。

31e98cfe-29ef-11ee-a368-dac502259ad0.jpg

實(shí)際上,這就是零拷貝技術(shù)。

它是操作系統(tǒng)提供的新函數(shù),同時(shí)接收文件描述符和 TCP socket 作為輸入參數(shù),這樣執(zhí)行時(shí)就可以不需要用戶層緩存,完全在內(nèi)核態(tài)完成內(nèi)存拷貝,既減少了內(nèi)存拷貝次數(shù),也降低了上下文切換次數(shù)。

而且,零拷貝取消了用戶緩沖區(qū)后,不只降低了用戶內(nèi)存的消耗,還通過(guò)最大化利用 socket 緩沖區(qū)中的內(nèi)存,間接地再一次減少了系統(tǒng)調(diào)用的次數(shù),從而帶來(lái)了大幅減少上下文切換次數(shù)的機(jī)會(huì)!

你可以回憶下,沒(méi)用零拷貝時(shí),為了傳輸 320MB 的文件,在用戶緩沖區(qū)分配了 32KB 的內(nèi)存,把文件分成 1 萬(wàn)份傳送,然而,這 32KB 是怎么來(lái)的?為什么不是 32MB 或者 32 字節(jié)呢?這是因?yàn)?,在沒(méi)有零拷貝的情況下,我們希望內(nèi)存的利用率最高。如果用戶緩沖區(qū)過(guò)大,它就無(wú)法一次性把消息全拷貝給 socket 緩沖區(qū);如果用戶緩沖區(qū)過(guò)小,則會(huì)導(dǎo)致過(guò)多的 read/write 系統(tǒng)調(diào)用。

那用戶緩沖區(qū)為什么不與 socket 緩沖區(qū)大小一致呢?這是因?yàn)?,socket 緩沖區(qū)的可用空間是動(dòng)態(tài)變化的,它既用于 TCP 滑動(dòng)窗口,也用于應(yīng)用緩沖區(qū),還受到整個(gè)系統(tǒng)內(nèi)存的影響。尤其在長(zhǎng)肥網(wǎng)絡(luò)中,它的變化范圍特別大。

零拷貝使我們不必關(guān)心 socket 緩沖區(qū)的大小。比如,調(diào)用零拷貝發(fā)送方法時(shí),盡可以把發(fā)送字節(jié)數(shù)設(shè)為文件的所有未發(fā)送字節(jié)數(shù),例如 320MB,也許此時(shí) socket 緩沖區(qū)大小為 1.4MB,那么一次性就會(huì)發(fā)送 1.4MB 到客戶端,而不是只有 32KB。這意味著對(duì)于 1.4MB 的 1 次零拷貝,僅帶來(lái) 2 次上下文切換,而不使用零拷貝且用戶緩沖區(qū)為 32KB 時(shí),經(jīng)歷了 176 次(4 * 1.4MB/32KB)上下文切換。

綜合上述各種優(yōu)點(diǎn),零拷貝可以把性能提升至少一倍以上!對(duì)文章開頭提到的 320MB 文件的傳輸,當(dāng) socket 緩沖區(qū)在 1.4MB 左右時(shí),只需要 4 百多次上下文切換,以及 4 百多次內(nèi)存拷貝,拷貝的數(shù)據(jù)量也僅有 640MB,這樣,不只請(qǐng)求時(shí)延會(huì)降低,處理每個(gè)請(qǐng)求消耗的 CPU 資源也會(huì)更少,從而支持更多的并發(fā)請(qǐng)求。

此外,零拷貝還使用了 PageCache 技術(shù),通過(guò)它,零拷貝可以進(jìn)一步提升性能,我們接下來(lái)看看 PageCache 是如何做到這一點(diǎn)的。

PageCache,磁盤高速緩存

回顧上文中的幾張圖,你會(huì)發(fā)現(xiàn),讀取文件時(shí),是先把磁盤文件拷貝到 PageCache 上,再拷貝到進(jìn)程中。為什么這樣做呢?有兩個(gè)原因所致。

第一,由于磁盤比內(nèi)存的速度慢許多,所以我們應(yīng)該想辦法把讀寫磁盤替換成讀寫內(nèi)存,比如把磁盤中的數(shù)據(jù)復(fù)制到內(nèi)存中,就可以用讀內(nèi)存替換讀磁盤。但是,內(nèi)存空間遠(yuǎn)比磁盤要小,內(nèi)存中注定只能復(fù)制一小部分磁盤中的數(shù)據(jù)。

選擇哪些數(shù)據(jù)復(fù)制到內(nèi)存呢?通常,剛被訪問(wèn)的數(shù)據(jù)在短時(shí)間內(nèi)再次被訪問(wèn)的概率很高(這也叫“時(shí)間局部性”原理),用 PageCache 緩存最近訪問(wèn)的數(shù)據(jù),當(dāng)空間不足時(shí)淘汰最久未被訪問(wèn)的緩存(即 LRU 算法)。讀磁盤時(shí)優(yōu)先到 PageCache 中找一找,如果數(shù)據(jù)存在便直接返回,這便大大提升了讀磁盤的性能。

第二,讀取磁盤數(shù)據(jù)時(shí),需要先找到數(shù)據(jù)所在的位置,對(duì)于機(jī)械磁盤來(lái)說(shuō),就是旋轉(zhuǎn)磁頭到數(shù)據(jù)所在的扇區(qū),再開始順序讀取數(shù)據(jù)。其中,旋轉(zhuǎn)磁頭耗時(shí)很長(zhǎng),為了降低它的影響,PageCache 使用了預(yù)讀功能。

也就是說(shuō),雖然 read 方法只讀取了 0-32KB 的字節(jié),但內(nèi)核會(huì)把其后的 32-64KB 也讀取到 PageCache,這后 32KB 讀取的成本很低。如果在 32-64KB 淘汰出 PageCache 前,進(jìn)程讀取到它了,收益就非常大。這一講的傳輸文件場(chǎng)景中這是必然發(fā)生的。

從這兩點(diǎn)可以看到 PageCache 的優(yōu)點(diǎn),它在 90% 以上場(chǎng)景下都會(huì)提升磁盤性能,但在某些情況下,PageCache 會(huì)不起作用,甚至由于多做了一次內(nèi)存拷貝,造成性能的降低。在這些場(chǎng)景中,使用了 PageCache 的零拷貝也會(huì)損失性能。

具體是什么場(chǎng)景呢?就是在傳輸大文件的時(shí)候。比如,你有很多 GB 級(jí)的文件需要傳輸,每當(dāng)用戶訪問(wèn)這些大文件時(shí),內(nèi)核就會(huì)把它們載入到 PageCache 中,這些大文件很快會(huì)把有限的 PageCache 占滿。

然而,由于文件太大,文件中某一部分內(nèi)容被再次訪問(wèn)到的概率其實(shí)非常低。這帶來(lái)了 2 個(gè)問(wèn)題:首先,由于 PageCache 長(zhǎng)期被大文件占據(jù),熱點(diǎn)小文件就無(wú)法充分使用 PageCache,它們讀起來(lái)變慢了;其次,PageCache 中的大文件沒(méi)有享受到緩存的好處,但卻耗費(fèi) CPU 多拷貝到 PageCache 一次。

所以,高并發(fā)場(chǎng)景下,為了防止 PageCache 被大文件占滿后不再對(duì)小文件產(chǎn)生作用,大文件不應(yīng)使用 PageCache,進(jìn)而也不應(yīng)使用零拷貝技術(shù)處理。

異步 IO + 直接 IO

高并發(fā)場(chǎng)景處理大文件時(shí),應(yīng)當(dāng)使用異步 IO 和直接 IO 來(lái)替換零拷貝技術(shù)。

仍然回到本講開頭的例子,當(dāng)調(diào)用 read 方法讀取文件時(shí),實(shí)際上 read 方法會(huì)在磁盤尋址過(guò)程中阻塞等待,導(dǎo)致進(jìn)程無(wú)法并發(fā)地處理其他任務(wù),如下圖所示:

31f3f6d0-29ef-11ee-a368-dac502259ad0.jpg

異步 IO(異步 IO 既可以處理網(wǎng)絡(luò) IO,也可以處理磁盤 IO,這里我們只關(guān)注磁盤 IO)可以解決阻塞問(wèn)題。它把讀操作分為兩部分,前半部分向內(nèi)核發(fā)起讀請(qǐng)求,但不等待數(shù)據(jù)就位就立刻返回,此時(shí)進(jìn)程可以并發(fā)地處理其他任務(wù)。當(dāng)內(nèi)核將磁盤中的數(shù)據(jù)拷貝到進(jìn)程緩沖區(qū)后,進(jìn)程將接收到內(nèi)核的通知,再去處理數(shù)據(jù),這是異步 IO 的后半部分。如下圖所示:

31fcb78e-29ef-11ee-a368-dac502259ad0.jpg

從圖中可以看到,異步 IO 并沒(méi)有拷貝到 PageCache 中,這其實(shí)是異步 IO 實(shí)現(xiàn)上的缺陷。經(jīng)過(guò) PageCache 的 IO 我們稱為緩存 IO,它與虛擬內(nèi)存系統(tǒng)耦合太緊,導(dǎo)致異步 IO 從誕生起到現(xiàn)在都不支持緩存 IO。

繞過(guò) PageCache 的 IO 是個(gè)新物種,我們把它稱為直接 IO。對(duì)于磁盤,異步 IO 只支持直接 IO。

直接 IO 的應(yīng)用場(chǎng)景并不多,主要有兩種:第一,應(yīng)用程序已經(jīng)實(shí)現(xiàn)了磁盤文件的緩存,不需要 PageCache 再次緩存,引發(fā)額外的性能消耗。比如 MySQL 等數(shù)據(jù)庫(kù)就使用直接 IO;第二,高并發(fā)下傳輸大文件,我們上文提到過(guò),大文件難以命中 PageCache 緩存,又帶來(lái)額外的內(nèi)存拷貝,同時(shí)還擠占了小文件使用 PageCache 時(shí)需要的內(nèi)存,因此,這時(shí)應(yīng)該使用直接 IO。

當(dāng)然,直接 IO 也有一定的缺點(diǎn)。除了緩存外,內(nèi)核(IO 調(diào)度算法)會(huì)試圖緩存盡量多的連續(xù) IO 在 PageCache 中,最后合并成一個(gè)更大的 IO 再發(fā)給磁盤,這樣可以減少磁盤的尋址操作;另外,內(nèi)核也會(huì)預(yù)讀后續(xù)的 IO 放在 PageCache 中,減少磁盤操作。直接 IO 繞過(guò)了 PageCache,所以無(wú)法享受這些性能提升。

有了直接 IO 后,異步 IO 就可以無(wú)阻塞地讀取文件了?,F(xiàn)在,大文件由異步 IO 和直接 IO 處理,小文件則交由零拷貝處理,至于判斷文件大小的閾值可以靈活配置(參見 Nginx 的 directio 指令)。

鏈接:https://www.cnblogs.com/-wenli/p/13380616.html





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編碼器
    +關(guān)注

    關(guān)注

    44

    文章

    3552

    瀏覽量

    133775
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    554

    瀏覽量

    100203
  • 數(shù)據(jù)交換
    +關(guān)注

    關(guān)注

    0

    文章

    99

    瀏覽量

    17905
  • cache技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    41

    瀏覽量

    1039
  • TCP通信
    +關(guān)注

    關(guān)注

    0

    文章

    146

    瀏覽量

    4192

原文標(biāo)題:如何高效實(shí)現(xiàn)文件傳輸:小文件采用零拷貝、大文件采用異步io+直接io

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何高效實(shí)現(xiàn)文件傳輸

    服務(wù)器提供文件傳輸功能,需要將磁盤上的文件讀取出來(lái),通過(guò)網(wǎng)絡(luò)協(xié)議發(fā)送到客戶端。如果需要你自己編碼實(shí)現(xiàn)這個(gè)文件傳輸功能,你會(huì)怎么
    發(fā)表于 08-01 16:16 ?494次閱讀
    如何高效<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>文件傳輸</b>

    關(guān)于基于labview的文件傳輸

    本帖最后由 eehome 于 2013-1-5 10:02 編輯 利用labview的datasocket的相關(guān)知識(shí),能實(shí)現(xiàn)些字符串從個(gè) 文本文件傳輸到另
    發(fā)表于 05-05 00:42

    文件傳輸解決方案

    文件傳輸個(gè)通用術(shù)語(yǔ),適用于通過(guò)計(jì)算機(jī)網(wǎng)絡(luò)傳輸數(shù)據(jù)的行為,私有或公共。托管文件傳輸旨在促進(jìn)文件傳輸,它是
    發(fā)表于 07-18 07:34

    Linux的文件傳輸

    Linux之文件傳輸
    發(fā)表于 05-26 09:01

    WinSCP文件傳輸工具分享

    WinSCP文件傳輸工具win和樹莓派下方便的數(shù)據(jù)傳輸軟件
    發(fā)表于 10-07 08:46

    基于線程池技術(shù)的文件傳輸模型的改進(jìn)

    本文首先就涉及的文件傳輸模型和線程池技術(shù)作了分析,在考慮了文件傳輸的特點(diǎn)后,結(jié)合線程池技術(shù)來(lái)對(duì)原來(lái)的文件傳輸模型提出了種改進(jìn)方案,從而提高了傳輸
    發(fā)表于 06-18 09:18 ?15次下載

    網(wǎng)絡(luò)文件傳輸源代碼

    易語(yǔ)言是門以中文作為程序代碼編程語(yǔ)言學(xué)習(xí)例程:易語(yǔ)言-網(wǎng)絡(luò)文件傳輸
    發(fā)表于 06-06 17:36 ?4次下載

    易語(yǔ)言-文件傳輸

    易語(yǔ)言是門以中文作為程序代碼編程語(yǔ)言學(xué)習(xí)例程:易語(yǔ)言-文件傳輸
    發(fā)表于 06-06 17:43 ?5次下載

    實(shí)現(xiàn)CFDP協(xié)議延時(shí)NAK模式文件傳輸

    當(dāng)前我國(guó)星上數(shù)據(jù)組織管理采用位流的形式,數(shù)據(jù)的下行傳輸沒(méi)有實(shí)現(xiàn)保證數(shù)據(jù)可靠性的機(jī)制,所有數(shù)據(jù)按比特流順序傳輸完成即結(jié)束,無(wú)法保證文件的有效性與完整性。空間數(shù)據(jù)系統(tǒng)咨詢委員
    發(fā)表于 11-05 11:33 ?2次下載
    <b class='flag-5'>實(shí)現(xiàn)</b>CFDP協(xié)議延時(shí)NAK模式<b class='flag-5'>文件傳輸</b>

    基于打包策略的文件傳輸策略

    基于互聯(lián)網(wǎng)的文件傳輸策略將直接影響到文件傳輸效率和網(wǎng)絡(luò)資源的使用效率,這情況在各種資源集中的云計(jì)算環(huán)境表現(xiàn)得更為明顯,特別是當(dāng)傳輸大量小文件
    發(fā)表于 12-06 14:06 ?1次下載

    WinSCP文件傳輸工具應(yīng)用程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是WinSCP文件傳輸工具應(yīng)用程序免費(fèi)下載。
    發(fā)表于 03-27 09:48 ?10次下載

    基于openharmony適配移植的web端與app端文件傳輸教程

    項(xiàng)目介紹 項(xiàng)目名稱:文件傳輸 所屬系列:openharmony的第三方組件適配移植 功能:web端與app端文件傳輸 項(xiàng)目移植狀態(tài):完成 調(diào)用差異:因網(wǎng)絡(luò)庫(kù)限制 暫不支持?jǐn)帱c(diǎn)續(xù)傳功能以及文件傳輸速度
    發(fā)表于 04-12 09:45 ?1次下載

    基于UDP的簡(jiǎn)單文件傳輸協(xié)議TFTP設(shè)計(jì)

    前面我們已經(jīng)實(shí)現(xiàn)了UDP的回環(huán)客戶端和回環(huán)服務(wù)器的簡(jiǎn)單應(yīng)用,接下來(lái)我們實(shí)現(xiàn)個(gè)基于UDP的簡(jiǎn)單文件傳輸協(xié)議TFTP。
    的頭像 發(fā)表于 12-14 15:06 ?2300次閱讀
    基于UDP的簡(jiǎn)單<b class='flag-5'>文件傳輸</b>協(xié)議TFTP設(shè)計(jì)

    文件管理器與文件傳輸的操作方法

    AnyDesk安力桌為在本地和遠(yuǎn)程端點(diǎn)之間文件傳輸,提供各種選項(xiàng)。這可以通過(guò) "文件管理器"會(huì)話或通過(guò)遠(yuǎn)程控制會(huì)話中的 "文件傳輸 "完成。
    的頭像 發(fā)表于 08-30 11:04 ?1364次閱讀

    如何實(shí)現(xiàn)文件傳輸

    會(huì)如何實(shí)現(xiàn)文件傳輸? 服務(wù)器提供文件傳輸功能,需要將磁盤上的文件讀取出來(lái),通過(guò)網(wǎng)絡(luò)協(xié)議發(fā)送到客戶端。如果需要你自己編碼
    的頭像 發(fā)表于 11-13 15:32 ?829次閱讀
    如何<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>文件傳輸</b>