為什麼緩衝區能提升性能?

學習驅動開發時看到一句話說輸出緩衝區幾乎總是能提升硬體性能。為什麼這樣說?


先做一個假設:

如果所有應用層訪問外設(如硬碟)都是4K/8K/16K...這種大小是規整的、地址是對齊的數據的話。那麼有沒有緩衝區意義不大。

顯然實際應用程序不可能是這樣的,應用程序訪問外部的數據可能是頻繁的小塊數據、不對齊的大塊數據、頻繁的讀寫某一塊數據。所以才需要緩衝區來提升性能。

要緩存,就要理解IOps (IO per Second)。所有存儲設備都有IOps的瓶頸,雖然SATA硬碟的匯流排速度是75MB/s或者150MB/s,但如果這是大塊數據才能達到的速度,如果每次讀取512位元組,那麼你會發現速度遠遠低於75MB/s,因為外設每秒處理的IO個數是有限的。緩存的作用之一就是把零散的IO合併成大塊的IO,降低IO請求的個數,提高性能。

緩存的另一個作用是預讀和數據重用,以我做文件系統的經驗表明:多數用戶讀取數據是連續進行的,如果用戶是每次讀32位元組,連續讀100MB數據,那麼預讀的意義就很大了,驅動層一次讀取4K數據,那麼用戶32位元組的讀請求實際只觸發一次IO操作。另外有些數據會重複讀取,比如文件索引等內容,有緩存就可以避免這些數據重複的執行真正的IO操作,提高性能

複雜的文件系統里,緩存的另一個作用是合併讀寫,比如對於一個文件的數據,先讀取,再寫入,再讀取,再寫入,執行10次,然後關閉文件。如果有緩存存在,那麼可能只有第一次讀和最後一次寫是真實的IO操作。其它的都是在操作緩存,這樣也可以提高性能。

當然,是不是緩存一定能提高性能?答案是否定的。

某些極端情況下,有緩存和無緩存差別不大,甚至有緩存更慢,比如:

一個32GB的文件,應用層每次讀1位元組,修改並寫回,然後文件指針向後移動256KB,再讀1位元組,修改並寫回。直到文件指針移動到32GB的最後。

這種操作模式會嚴重干擾緩存,不管是預讀還是合併IO都失去意義,這種情況下緩存反而是負擔。


做一個不恰當也不全面但是感覺比較直觀比喻:

你有一盒子牙籤,200根全掉在地上了,你的全都撿回桌子上。

-----------不用緩衝的方式------------

  你蹲下,用右手拿一根牙籤,站起來,把那根牙籤放在桌子上。

  重複這個動作200次。

-----------用緩衝的方式----------------

  你蹲下,用右手拿一根牙籤,放在左手上。等你的左手拿不下了,站起來把左手的牙籤都放在桌上。

  再蹲下重複。

  在這個方式中,你的左手就是緩衝。緩衝能提交效率的原理就是減少了「蹲下/站起」這個比較費力費時的動作的次數


添加個非專業答案,經常有人問的問題,你寫個條貼旁邊兒,大家自己看,比你一個一個解釋來得快吧。要是問題實在太多,你多寫幾張,加大緩存,就快了。


推薦閱讀:

程序員是否需要大尺寸的顯示器?
coursera上有哪些值得學習的Python,數據分析的課程?
為什麼C++的逗號運算符是可以重載的?
模擬示波器通常是什麼樣的架構什麼系統,如何編程(有人在日立V-422上編寫了一款FPS遊戲)?

TAG:軟體 | 編程 | 計算機 | C編程語言 | 驅動程序開發 |