www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 公眾號精選 > 架構師社區(qū)
[導讀]計算機處理的任務大體可以分為兩類:CPU密集型與IO密集型。當前流行的互聯(lián)網應用更多的屬于IO密集型,傳統(tǒng)的IO標準接口都是基于數(shù)據(jù)拷貝的,這篇文章我們主要關注該怎樣從數(shù)據(jù)拷貝的角度來優(yōu)化IO性能,讓你的程序在IO性能方面趕超P8。為什么IO接口要基于數(shù)據(jù)拷貝?為了讓廣大碼農們更...

計算機處理的任務大體可以分為兩類:CPU密集型與IO密集型。

當前流行的互聯(lián)網應用更多的屬于IO密集型,傳統(tǒng)的IO標準接口都是基于數(shù)據(jù)拷貝的,這篇文章我們主要關注該怎樣從數(shù)據(jù)拷貝的角度來優(yōu)化IO性能,讓你的程序在IO性能方面趕超P8。

為什么IO接口要基于數(shù)據(jù)拷貝?

為了讓廣大碼農們更好的沉迷于自己的一畝三分地,防止ta們分心去關心計算機中的硬件資源分配問題,操作系統(tǒng)誕生了。

操作系統(tǒng)本質上就是一個管家,目的就是更加公平合理的給各個進程分配硬件資源,在操作系統(tǒng)出現(xiàn)之前,程序員需要直面各類硬件,就像這樣:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

在這一時期程序員真可謂掌控全局,掌控全局帶來的后果就是你需要掌控所有細節(jié),這顯然不利于生產力的釋放。

操作系統(tǒng)應用而生。

計算機系統(tǒng)就變成這樣了:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

現(xiàn)在應用程序不需要和硬件直接交互了,僅從IO的角度上看,操作系統(tǒng)變成了一個類似路由器的角色,把應用程序遞交過來的數(shù)據(jù)分發(fā)到具體的硬件上去,或者從硬件接收數(shù)據(jù)并分發(fā)給相應的進程。

數(shù)據(jù)傳遞是通過什么呢?就是我們常說的buffer,所謂buffer就是一塊可用的內存空間,用來暫存數(shù)據(jù)。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

操作系統(tǒng)這一中間商導致的問題就是:你需要首先把東西交給操作系統(tǒng),操作系統(tǒng)再轉手交給硬件,這就必然涉及到數(shù)據(jù)拷貝。

這就是為什么傳統(tǒng)的IO操作必然需要進行數(shù)據(jù)拷貝的原因所在。關于操作系統(tǒng)系統(tǒng)完整的闡述請參見博主的《深入理解操作系統(tǒng)》。

然而數(shù)據(jù)拷貝是有性能損耗的,接下來我們用一個實例來讓大家對該問題有一個更直觀的認知。

網絡服務器

瀏覽器打開一個網頁需要很多數(shù)據(jù),包括看到的圖片、html文件、css文件、js文件等等,當瀏覽器請求這類文件時服務器端的工作其實是非常簡單的:服務器只需要從磁盤中抓出該文件然后丟給網絡發(fā)送出去。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

代碼基本上類似這樣:

read(fileDesc,?buf,?len);
write(socket,?buf,?len);
這兩段代碼非常簡單,第一行代碼從文件中讀取數(shù)據(jù)存放在buf中,然后將buf中的數(shù)據(jù)通過網絡發(fā)送出去。

注意觀察buf,服務器全程沒有對buf中的數(shù)據(jù)進行任何修改,buf里的數(shù)據(jù)在用戶態(tài)逛了一圈后揮一揮衣袖沒有帶走半點云彩就回到了內核態(tài)。

這兩行看似簡單的代碼實際上在底層發(fā)生了什么呢?

答案是這樣的:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

在程序看來簡單的兩行代碼在底層是比較復雜的,看到這張圖你應該真心感激操作系統(tǒng),操作系統(tǒng)就像一個無比稱職的管家,替你把所有臟活累活都承擔下來,好讓你悠閑的在用戶態(tài)指點江山。

這簡單的兩行代碼涉及:四次數(shù)據(jù)拷貝以及四次上下文切換:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

  1. read函數(shù)會涉及一次用戶態(tài)到內核態(tài)的切換,操作系統(tǒng)會向磁盤發(fā)起一次IO請求,當數(shù)據(jù)準備好后通過DMA技術把數(shù)據(jù)拷貝到內核的buffer中,注意本次數(shù)據(jù)拷貝無需CPU參與。
  2. 此后操作系統(tǒng)開始把這塊數(shù)據(jù)從內核拷貝到用戶態(tài)的buffer中,此時read()函數(shù)返回,并從內核態(tài)切換回用戶態(tài),到這時read(fileDesc, buf, len);這行代碼就返回了,buf中裝好了新鮮出爐的數(shù)據(jù)。
  3. 接下來send函數(shù)再次導致用戶態(tài)與內核態(tài)的切換,此時數(shù)據(jù)需要從用戶態(tài)buf拷貝到網絡協(xié)議子系統(tǒng)的buf中,具體點該buf屬于在代碼中使用的這個socket。
  4. 此后send函數(shù)返回,再次由內核態(tài)返回到用戶態(tài);此時在程序員看來數(shù)據(jù)已經成功發(fā)出去了,但實際上數(shù)據(jù)可能依然停留在內核中,此后第四次數(shù)據(jù)copy開始,利用DMA技術把數(shù)據(jù)從socket buf拷貝給網卡,然后真正的發(fā)送出去。
這就是看似簡單的這兩行代碼在底層的完整過程。

你覺得這個過程有什么問題嗎?

發(fā)現(xiàn)問題

有的同學肯定已經注意到了,既然在用戶態(tài)沒有對數(shù)據(jù)進行任何修改,那為什么要這么麻煩的讓數(shù)據(jù)在用戶態(tài)來個一日游呢?直接在內核態(tài)從磁盤給到網卡不就可以了嗎?

恭喜你,答對了!

這種優(yōu)化思路就是所謂的零拷貝技術,Zero Copy。

總體上來看,優(yōu)化數(shù)據(jù)拷貝會有以下三個方向:

  1. 用戶態(tài)不需要真正的去訪問數(shù)據(jù),就像上面這個示例,用戶態(tài)根本不需要知道buf里面裝的是什么。在這種情況下無需把數(shù)據(jù)從內核態(tài)拷貝到用戶態(tài)然后再把數(shù)據(jù)從用戶態(tài)拷貝回內核態(tài)。

    數(shù)據(jù)無需用戶態(tài)感知,數(shù)據(jù)拷貝完全發(fā)生在內核態(tài)。

  2. 內核態(tài)不要真正的去訪問數(shù)據(jù),用戶態(tài)程序可以繞過內核直接和硬件交互,這樣就避免了內核的參與,從而減少數(shù)據(jù)拷貝的可能。

    內核無需感知數(shù)據(jù)。

  3. 如果內核態(tài)和用戶態(tài)不得不進行數(shù)據(jù)交互,則優(yōu)化用戶態(tài)與內核態(tài)數(shù)據(jù)的交互方式。

知道了解決問題的思路,我們來看下為了實現(xiàn)零拷貝,計算機系統(tǒng)中都有哪些巧妙的設計。

mmap

是的,就是mmap,在《mmap可以讓程序員實現(xiàn)哪些騷操作》一文中我們對其進行了詳細講解,你能想到mmap還可以實現(xiàn)零拷貝嗎?

對于本文提到的網絡服務器我們可以這樣修改代碼:

buf?=?mmap(file,?len);
write(socket,?buf,?len);
你可能會想僅僅將read替換為mmap會有什么優(yōu)化嗎?

如果你真的理解了mmap就會知道,mmap僅僅將文件內容映射到了進程地址空間中,并沒有真正的拷貝到進程地址空間,這節(jié)省了一次從內核態(tài)到用戶態(tài)的數(shù)據(jù)拷貝。

同樣的,當調用write時數(shù)據(jù)直接從內核buf拷貝給了socket buf,而不是像read/write方法中把用戶態(tài)數(shù)據(jù)拷貝給socket buf。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

我們可以看到,利用mmap我們節(jié)省了一次數(shù)據(jù)拷貝,上下文切換依然是四次。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

盡管mmap可以節(jié)省數(shù)據(jù)拷貝,但維護文件與地址空間的映射關系也是有代價的,除非CPU拷貝數(shù)據(jù)的時間超過維系映射關系的代價,否則基于mmap的程序性能可能不及傳統(tǒng)的read/write。

此外,如果映射的文件被其它進程截斷,在Linux系統(tǒng)下你的進程將立即接收到SIGBUS信號,因此這種異常情況也需要正確處理。

除了mmap之外,還有其它辦法也可以實現(xiàn)零拷貝。

sendfile

你沒有看錯,在Linux系統(tǒng)下為了解決數(shù)據(jù)拷貝問題專門設計了這一系統(tǒng)調用:

#include?
ssize_t?sendfile(int?out_fd,?int?in_fd,?off_t?*offset,?size_t?count);
Windows下也有一個作用類似的API:TransmitFile。

這一系統(tǒng)調用的目的是在兩個文件描述之間拷貝數(shù)據(jù),但值得注意的是,數(shù)據(jù)拷貝的過程完全是在內核態(tài)完成,因此在網絡服務器的這個例子中我們將把那兩行代碼簡化為一行,也就是調用這里的sendfile。

使用sendfile將節(jié)省兩次數(shù)據(jù)拷貝,因為數(shù)據(jù)無需傳輸?shù)接脩魬B(tài):

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

調用sendfile后,首先DMA機制會把數(shù)據(jù)從磁盤拷貝到內核buf中,接下來把數(shù)據(jù)從內核buf拷貝到相應的socket buf中,最后利用DMA機制將數(shù)據(jù)從socket buf拷貝到網卡中。

我們可以看到,同使用傳統(tǒng)的read/write相比少了一次數(shù)據(jù)拷貝,而且內核態(tài)和用戶態(tài)的切換只有兩次。

有的同學可能已經看出了,這好像不是拷貝吧,在內核中這不是還有一次從內核態(tài)buf到socket buf的數(shù)據(jù)拷貝嗎?這次拷貝看上去也是沒有必要的。

的確如此,為解決這一問題,單純的軟件機制已經不夠用了,我們需要硬件來幫一點忙,這就是DMA Gather Copy。

sendfile 與DMA Gather Copy

傳統(tǒng)的DMA機制必須從一段連續(xù)的空間中傳輸數(shù)據(jù),就像這樣:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

很顯然,你需要在源頭上把所有需要的數(shù)據(jù)都拷貝到一段連續(xù)的空間中:

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

現(xiàn)在肯定有同學會問,為什么不直接讓DMA可以從多個源頭收集數(shù)據(jù)呢?

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

這就是所謂的DMA Gather Copy。

有了這一特性,無需再將內核文件buf中的數(shù)據(jù)拷貝到socket buf,而是網卡利用DMA Gather Copy機制將消息頭以及需要傳輸?shù)臄?shù)據(jù)等直接組裝在一起發(fā)送出去。

在這一機制的加持下,CPU甚至完全不需要接觸到需要傳輸?shù)臄?shù)據(jù),而且程序利用sendfile編寫的代碼也無需任何改動,這進一步提升了程序性能。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

當前流行的消息中間件kafka就基于sendfile來高效傳輸文件。

其實你應該已經看出來了,高效IO的秘訣其實很簡單:盡量少讓CPU參與進來

實際上sendfile的使用場景是比較受限的,大前提是用戶態(tài)無需看到操作的數(shù)據(jù),并且只能從文件描述符往socket中傳輸數(shù)據(jù),而且DMA Gather Copy也需要硬件支持,那么有沒有一種不依賴硬件特性同時又能在任意兩個文件描述符之間以零拷貝方式高效傳遞數(shù)據(jù)的方法呢?

答案是肯定的!這就要說到Linux下的另一個系統(tǒng)調用了:splice。

Splice

這里還要再次強調一下不管是sendfile還是這里的splice系統(tǒng)調用,使用的大前提都是無需在用戶態(tài)看到要傳遞的數(shù)據(jù)。

讓我們再來看一下傳統(tǒng)的read/write方法。

在這一方法下必須將數(shù)據(jù)從內核態(tài)拷貝的用戶態(tài),然后在從用戶態(tài)拷貝回內核態(tài),既然用戶態(tài)無需對該數(shù)據(jù)有任何操作,那么為什么不讓數(shù)據(jù)傳輸直接在內核態(tài)中進行呢?

現(xiàn)在目標有了,實現(xiàn)方法呢?

答案是借助Linux世界中用于進程間通信的管道,pipe。

還是以網絡服務器為例,DMA把數(shù)據(jù)從磁盤拷貝到文件buf,然后將數(shù)據(jù)寫入管道,當在再次調用splice后將數(shù)據(jù)從管道讀入socket buf中,然后通過DMA發(fā)送出去,值得注意的是向管道寫數(shù)據(jù)以及從管道讀數(shù)據(jù)并沒有真正的拷貝數(shù)據(jù),而僅僅傳遞的是該數(shù)據(jù)相關的必要信息。

為什么?P8?程序員的代碼你寫不出來?零拷貝了解一下

你會看到,splice和sendfile是很像的,實際上后來sendfile系統(tǒng)調用經過改造后就是基于splice實現(xiàn)的,既然有splice那么為什么還要保留sendfile呢?答案很簡單,如果直接去掉sendfile,那么之前依賴該系統(tǒng)調用的所有程序將無法正常運行。

總結

本文介紹了很多零拷貝的優(yōu)化技巧,但是注意,一定要注意,如果你的程序對性能要沒有到那種極度苛刻哪怕慢1ns都不行的時候,忘掉本文講解的這些所謂優(yōu)化技巧,老老實實用read/write,相比這些所謂的技巧,內存拷貝沒有那么糟糕。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉