磁盤I/O介紹

  • Linux 文件系統簡介
    • 影響硬盤性能的因素
      • 影響磁盤的關鍵因素是磁盤服務時間, 即磁盤完成一個I/O請求所花費的時間, 它由尋道時間、旋轉延遲和數據傳輸時間三部分構成.
        • 尋道時間
          • Tseek是指將讀寫磁頭移動至正確的磁道上所需要的時間. 尋道時間越短, I/O操作越快, 目前磁盤的平均尋道時間一般在3-15ms.
        • 旋轉延遲
          • Trotation是指盤片旋轉將請求數據所在的扇區移動到讀寫磁盤下方所需要的時間. 旋轉延遲取決於磁盤轉速, 通常用磁盤旋轉一周所需時間的1/2表示.
          • 比如:7200 rpm 的磁盤平均旋轉延遲大約為60*1000/7200/2 = 4.17ms, 而轉速為15000rpm的磁盤其平均旋轉延遲為2ms.
        • 數據傳輸時間
          • Ttransfer是指完成傳輸所請求的數據所需要的時間, 它取決於數據傳輸率, 其值等於數據大小除以數據傳輸率.
          • 目前IDE/ATA能達到133MB/s, SATA II可達到300MB/s的接口數據傳輸率, 數據傳輸時間通常遠小於前兩部分消耗時間. 簡單計算時可忽略.
    • 衡量性能的指標
      • 機械硬盤的連續讀寫性能很好, 但隨機讀寫性能很差, 這主要是因為磁頭移動到正確的磁道上需要時間, 隨機讀寫時, 磁頭需要不停的移動, 時間都浪費在瞭磁頭尋址上, 所以性能不高. 衡量磁盤的重要主要指標是IOPS和吞吐量.
        • IOPS
          • 7200rpm的磁盤 IOPS = 76 IOPS
          • 10000rpm的磁盤IOPS = 111 IOPS
          • 15000rpm的磁盤IOPS = 166 IOPS
        • 吞吐量
          • 吞吐量(Throughput), 指單位時間內可以成功傳輸的數據數量. 順序讀寫頻繁的應用, 如視頻點播, 關註連續讀寫性能、數據吞吐量是關鍵衡量指標.
  • read / write
    • 在現代操作系統中, 一個 “真正的” 文件, 當調用 read / write 的時候, 數據當然不會簡單地就直達硬盤. 對於 Linux 而言, 這個過程的一部分是這樣的:
    • 在操作系統內核空間內, read / write 到硬件設備之間, 按順序有這麼幾層:
      • VFS:虛擬文件系統, 可以大致理解為 read / write / ioctl 之類的系統調用就在這一層. 當調用 open 之後, 內核會為每一個 file descriptor 創建一個 file_operations 結構體實例. 這個結構體裡包含瞭 open、write、seek 等的實例(回調函數). 這一層其實是 Linux 文件和設備體系的精華之一, 很多東西都隱藏或暴露在這一層. 不過本文不研究這一塊
      • 文件系統: 這一層是實際的文件系統實現層, 向上隱藏瞭實現細節. 當然, 實際上除瞭文件系統之外, 還包含其他的虛擬文件, 包括設備節點、/proc 文件等等
      • buffer cache:這就是本文所說的 “緩存”. 後文再講.
      • 設備驅動:這是具體硬件設備的設備驅動瞭, 比如 SSD 的讀寫驅動、磁盤的讀寫驅動、字符設備的讀寫驅動等等.
      • 硬件設備
    • 從系統調用角度

      • 進程向內核發起一個系統調用,
      • 內核接收到系統調用, 知道是對文件的請求, 於是告訴磁盤, 把文件讀取出來
      • 磁盤接收到來著內核的命令後, 把文件載入到內核的內存空間裡面 (第一次 copy)
      • 內核的內存空間接收到數據之後, 把數據 copy 到用戶進程的內存空間(第二次 copy)
      • 進程內存空間得到數據後, 給內核發送通知
      • 內核把接收到的通知回復給進程, 此過程為喚醒進程, 然後進程得到數據, 進行下一步操作
    • MMAP
      • mmap 把文件映射到用戶空間裡的虛擬內存, 省去瞭從內核緩沖區復制到用戶空間的過程, 文件中的位置在虛擬內存中有瞭對應的地址, 可以像操作內存一樣操作這個文件, 相當於已經把整個文件放入內存, 但在真正使用到這些數據前卻不會消耗物理內存, 也不會有讀寫磁盤的操作, 隻有真正使用這些數據時, 虛擬內存管理系統 VMS 才根據缺頁加載的機制從磁盤加載對應的數據塊到物理內存進行渲染. 這樣的文件讀寫文件方式少瞭數據從內核緩存到用戶空間的拷貝, 效率很高.
        • 比較適用小文件隨機 IO, 比如說索引
          • 要提前確定大小
          • Java 中的 mmap 回收比較蛋疼
          • MMAP 使用的是虛擬內存, 和 PageCache 一樣是由操作系統來控制刷盤的, 可以通過 force 強刷

    • 普通流程(read/send)
      • OS 將數據從磁盤復制到操作系統內核的頁緩存中 (磁盤(DMA) -> kernel buffer, U -> K)
      • 應用將數據從內核空間復制到應用的用戶空間 (kernel buffer -> user space buffer, K -> U)
      • 應用將數據復制回內核態的 Socket 緩存中 (user space buffer -> kernel buffer, U -> K)
      • OS 將Socket緩存復制到網卡發出 (kernel buffer -> 網卡(DMA))
      • 1,2 步是 read, 3,4 步是 send, 整個過程總共發生瞭四次拷貝和四次的用戶態和內核態的切換.

    • Zero copy (sendfile)
      • OS 將數據從磁盤復制到操作系統內核的頁緩存中 (磁盤(DMA) -> kernel buffer, U -> K)
      • 內核的頁緩存復制到內核態的 Socket 緩存中 (kernel buffer -> Socket kernel buffer)
      • OS 將Socket緩存復制到網卡發出 (kernel buffer -> 網卡(DMA))
      • 如果網卡支持 gather operations 內核就可以進一步減少數據拷貝:
          • OS 將數據從磁盤復制到操作系統內核的頁緩存中 (磁盤(DMA) -> kernel buffer, U -> K)
          • 無數據被復制到 Socket buffer. 隻是描述瞭需要被寫入的數據的位置和長度. DMA直接把數據從 kernel buffer 復制到網卡(DMA gather copy)
    • PAGE CACHE層
      • 引入Cache層的目的是為瞭提高Linux操作系統對磁盤訪問的性能. Cache層在內存中緩存瞭磁盤上的部分數據. 當數據的請求到達時, 如果在Cache中存在該數據且是最新的, 則直接將數據傳遞給用戶程序, 免除瞭對底層磁盤的操作, 提高瞭性能. Cache層也正是磁盤IOPS為什麼能突破200的主要原因之一.
      • 在Linux的實現中, 文件Cache分為兩個層面, 一是Page Cache, 另一個Buffer Cache, 每一個Page Cache包含若幹Buffer Cache. Page Cache主要用來作為文件系統上的文件數據的緩存來用, 尤其是針對當進程對文件有read/write操作的時候. Buffer Cache則主要是設計用來在系統對塊設備進行讀寫的時候, 對塊進行數據緩存的系統來使用.
      • 磁盤Cache有兩大功能:預讀和回寫.

赞(0)