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