為什么 CPU 訪問硬盤很慢
機械硬盤(Hard Disk Drive、HDD)和固態(tài)硬盤(Solid State Drive、SSD)是兩種最常見的硬盤,作為計算機的外部存儲,CPU 想要訪問它們存儲的數(shù)據(jù)需要很長時間,如下表所示,在 SSD 中隨機訪問 4KB 數(shù)據(jù)所需要的時間是訪問主存的 1,500 倍,機械磁盤的尋道時間是訪問主存的 100,000 倍:
表 1 - 2012 年延遲數(shù)字對比[^1]
雖然磁盤的尋道時間只需要 10ms,但是在 CPU 看來已經(jīng)是非常長的時間了,當(dāng)我們將上述的時間等比例放大后,就能直觀地感受到它們的性能差異。如果 CPU 訪問 L1 緩存需要 1 秒,那么訪問主存需要 3 分鐘、從 SSD 中隨機讀取數(shù)據(jù)需要 3.4 天、磁盤尋道需要 2 個月,網(wǎng)絡(luò)傳輸可能需要 1 年多的時間。
在計算機體系結(jié)構(gòu)中,硬盤屬于一種常見的輸入輸出設(shè)備,操作系統(tǒng)在啟動時不一定需要硬盤,它既可以通過硬盤啟動,也可以通過網(wǎng)絡(luò)設(shè)備或者外部設(shè)備啟動,所以硬盤不是計算機運行的必要條件。
圖 1 - 輸入輸出設(shè)備
作為一種外部的輸入輸出設(shè)備,與 CPU 緩存和內(nèi)存相比,硬盤極慢的讀取和寫入速度就顯得比較合理了,然而幾千倍甚至幾十萬倍的速度差異也確實讓人很難想象或者接受,在這篇文章中,我們會分析為什么 CPU 訪問硬盤的速度非常慢:
- CPU 訪問硬盤數(shù)據(jù)的過程比較復(fù)雜,它會先通過 I/O 操作將磁盤中的數(shù)據(jù)讀入內(nèi)存,再訪問內(nèi)存的數(shù)據(jù);
- 機械硬盤在訪問磁盤中的數(shù)據(jù)依賴的是機械結(jié)構(gòu),需要移動磁盤中的機械臂;
I/O 操作
CPU 想要訪問磁盤中的數(shù)據(jù)一定要先通過 I/O 操作將磁盤中的數(shù)據(jù)讀入到內(nèi)存中,再訪問存儲在內(nèi)存中的數(shù)據(jù)。計算機中包含三種比較常見的 I/O 操作[^2] — 編程 I/O(Programmed I/O)、中斷驅(qū)動 I/O(Interrupt-driven I/O)和直接內(nèi)存訪問(Direct Memory Access),我們接下來將依次介紹上述的這幾種操作[^3]:
圖 2 - 常見 I/O 操作
執(zhí)行 I/O 操作最簡單的形式就是使用編程 I/O,使用編程 I/O 時,CPU 會負責(zé)全部的工作,如果我們想要在屏幕上輸出 Hello World,CPU 每次都會向 I/O 設(shè)備中寫入一個新字符,寫入后會輪詢設(shè)備的狀態(tài)等待它完成工作后寫入新的字符。這種方式雖然簡單,但是它會占用全部的 CPU 資源,在某些復(fù)雜的系統(tǒng)中會造成計算資源的嚴重浪費。
中斷驅(qū)動 I/O 是執(zhí)行 I/O 操作的一種更高效方式,在編程 I/O 中,CPU 會主動獲取設(shè)備的狀態(tài)并等待設(shè)備閑置,但是如果使用了中斷驅(qū)動 I/O,設(shè)備會在閑置時主動發(fā)起中斷暫停當(dāng)前進程并保存上下文,而操作系統(tǒng)會執(zhí)行 I/O 設(shè)備的中斷處理程序:
- 如果當(dāng)前不包含待打印的字符,停止中斷處理程序并恢復(fù)暫停的進程;
- 如果當(dāng)前包含待打印的字符,將下一個字符拷貝到設(shè)備中并恢復(fù)暫停的進程;
使用中斷驅(qū)動 I/O 可以在設(shè)備繁忙時,讓 CPU 能夠處理其它任務(wù),盡可能地提高 CPU 的利用率,不再浪費珍貴的計算資源。與編程 I/O 相比,中斷驅(qū)動 I/O 將一部分工作交給了 I/O 設(shè)備,所以能夠提高資源的利用率。
直接內(nèi)存訪問會利用 DMA 控制器來執(zhí)行 I/O 操作,中斷驅(qū)動 I/O 需要為每個字符觸發(fā)操作系統(tǒng)中斷,這會消耗一定的 CPU 時間。當(dāng)我們使用 DMA 控制器時,CPU 會一次將緩沖區(qū)中的數(shù)據(jù)全部讀到 DMA 控制器中,DMA 控制器會負責(zé)將數(shù)據(jù)按字符寫入 I/O 設(shè)備:
圖 3 - DMA I/O
雖然 DMA 控制器可以解放 CPU 并減少中斷次數(shù),但是它的執(zhí)行速度與 CPU 相比卻很慢,如果 DMA 控制器不能快速驅(qū)動 I/O 設(shè)備,CPU 可能就會等待 DMA 控制器觸發(fā)中斷,在這種情況下,中斷驅(qū)動 I/O 或者編程 I/O 可以提供更快的訪問速度。
在默認情況下,我們都會使用 DMA 控制器來執(zhí)行 I/O 任務(wù),不過編程 I/O 和中斷驅(qū)動 I/O 也不是不能接受的選項。當(dāng) CPU 經(jīng)常需要等待 DMA 控制器執(zhí)行 I/O 任務(wù)時,使用中斷驅(qū)動 I/O 甚至輪詢的編程 I/O 都可以得到更高的吞吐量,然而無論使用哪種方式,I/O 都是程序中比較耗時的復(fù)雜操作。
機械硬盤
機械硬盤(Hard Disk Drive、HDD)是一種基于電子的、非易失的機械數(shù)據(jù)存儲設(shè)備,它使用磁性存儲器存儲并查找磁盤上的數(shù)據(jù),在讀取和寫入數(shù)據(jù)的過程中,硬盤機械臂連接的磁頭會讀寫磁盤表面的位[^8]。
正是因為磁盤具有比較復(fù)雜的機械結(jié)構(gòu),所以磁盤的讀取和寫入都要花費很多時間,數(shù)據(jù)庫的讀寫性能也基本都依賴于磁盤的性能,如果我們在使用機械硬盤的數(shù)據(jù)庫中隨機查詢一條數(shù)據(jù),這可能會觸發(fā)磁盤的隨機 I/O,然而將數(shù)據(jù)從磁盤讀取到內(nèi)存中所需要的成本是非常大的,普通磁盤(非 SSD)加載數(shù)據(jù)需要經(jīng)過隊列、尋道、旋轉(zhuǎn)以及傳輸?shù)倪@些過程,大概要花費 10ms 左右的時間。
圖 4 - 磁盤的隨機 I/O
我們在估算數(shù)據(jù)庫的查詢時可以使用 10ms 這個數(shù)量級對隨機 I/O 占用的時間進行估算,這里想要說的是隨機 I/O 對于數(shù)據(jù)庫的查詢性能影響會非常大,而順序讀取磁盤中的數(shù)據(jù)時速度可以達到 40MB/s,這兩者的性能差距有幾個數(shù)量級,因此我們也應(yīng)該盡量減少隨機 I/O 的次數(shù),這樣才能提高性能。
固態(tài)硬盤(Solid State Drive、SSD)是一種以閃存作為持久存儲器的電腦存儲設(shè)備[^9]。與機械硬盤不同,固態(tài)硬盤中不包含任何的機械結(jié)構(gòu),我們使用它讀取或者存儲數(shù)據(jù)時不會使用到任何的機械結(jié)構(gòu),因為一切過程都是由電路完成的,所以 SSD 的讀寫速度比 HDD 快很多。
圖 5 - HDD 和 SSD 的價格
機械硬盤和 SSD 從誕生后價格都在不斷降低,機械硬盤是今天數(shù)據(jù)中心使用的主要外部存儲,大多數(shù)通用的商用服務(wù)器都會使用機械硬盤作為主要的外部存儲,但是因為 SSD 的讀寫速度是機械硬盤的幾十倍,所以越來越多的服務(wù)器,尤其是數(shù)據(jù)庫都會使用 SSD 作為外部存儲。不過作為具有機械結(jié)構(gòu)的外部存儲設(shè)備,它雖然結(jié)構(gòu)非常成熟并且具有較大的容量,但是它在受到震動時很容易受到外界的干擾。
總結(jié)
硬盤是計算機上的外部存儲設(shè)備,它可以持久存儲大量數(shù)據(jù),然而 CPU 無法直接訪問硬盤中的數(shù)據(jù),當(dāng)計算機啟動時操作系統(tǒng)會將硬盤中的數(shù)據(jù)加載到內(nèi)存中以便 CPU 訪問,但是如果 CPU 要訪問的數(shù)據(jù)不在內(nèi)存中,那么我們需要花費幾千倍甚至幾十萬倍的時間來讀取數(shù)據(jù),這主要是由以下兩個原因造成的:
- CPU 需要通過 I/O 操作訪問外部存儲中的數(shù)據(jù),編程 I/O、中斷驅(qū)動 I/O 和 DMA 幾種方式都會帶來額外開銷并占用較多的 CPU 時間;
- 機械硬盤會通過機械結(jié)構(gòu)訪問其中存儲的數(shù)據(jù),每一次硬盤的隨機 I/O 都需要執(zhí)行隊列、尋道、旋轉(zhuǎn)和轉(zhuǎn)移數(shù)據(jù)幾個過程,大約需要消耗 10ms 的時間;
正如我們在文章中提到的,硬盤不是計算機運行的必要硬件設(shè)備,計算機可以從磁盤、光盤等任意外部存儲設(shè)備中將啟動所需要的數(shù)據(jù)加載到內(nèi)存中并正常啟動,不過硬盤已經(jīng)是今天最為常見的外部存儲設(shè)備了。到最后,我們還是來看一些比較開放的相關(guān)問題,有興趣的讀者可以仔細思考一下下面的問題:
- 寫入到硬盤上的數(shù)據(jù)一定會被持久存儲,不會丟失嗎?
- 內(nèi)存中的數(shù)據(jù)為什么在斷電重啟之后就會被清空?