文章目錄
- NVME 和 AHCI 性能比較
- NVME-CLI nvme工具使用
- 1. 安裝
- 2. 指令綜述
- 3. 基本指令示範
- 4. NVME 固件裝置更新
近期在做一些rocksdb on 新硬體的性能測試(flash ssd, nvme ssd , nvme optane ssd, optane persistent memory),由于底層一些裝置的實作對我來說還是知識盲區,一些裝置IO表現出來的行為完全是黑盒,讓人琢磨不透。
是以利用周末時間對基礎的AHCI + SATA 排程的傳統ssd 和 基于 NVME 協定排程的ssd 做了一個入門了解。
細粒度的參考可以直接讀官方文檔:NVME-doc
NVME 和 AHCI 性能比較
NAND 閃存是傳統ssd的存儲媒體。早期的ssd通過上層的AHCI(advanced host controller interface) + SATA協定進行作業系統的塊裝置驅動層到底層實體裝置的IO排程,但是這樣的組合AHCI + SATA 是為了傳統的HDD機械硬碟設計的,在如今ssd内部核心技術的快速發展中已經無法發揮出底層SSD的低延時和高性能的優勢。為了發揮SSD高性能,固件廠商為SSD量身打造了一個協定标準NVME( Non-Volatile Memeory Express),且這個标準不僅可以應用在NAND的存儲媒體上,也能夠應用在高性能和低延時的3D XPoint 新型媒體上。
整體的NVME 協定架構如下,總共分為四層,到最底層就是 nvme的subsystem:
nvme的subsystem
NVME和AHCI 相比的優勢主要是以下三個方面:
-
低延時(Latency)
傳統的HDD+sas/sata 随機讀延時大概在ms量級
NAND ssd + sas/sata 随機讀延時在110us 左右
基于NVME的NAND ssd 随機讀延時在85us 左右,相比于sata的nand ssd 延時降低了20 us
當然3D XPoint + nvme 這樣的新型存儲媒體 延時隻有10us左右(intel Optane p4800),這樣的硬體紅利帶來的效果還是很給力的。
以上的延時都會展現在上層的應用之中,尤其是新型存儲媒體搭配nvme協定 展現出的低延時 對上層應用的正向回報還是十分給力的。而且intel 近期仍然會推出更為給力的p5800(iops 和帶寬 相比于p4800 提升一倍以上,latency會降低40%-50%)。
實作上來看,對硬碟存儲延時有影響的如下幾種:
- 存儲媒體層面,閃存比傳統的機械硬碟快很多。(NAND是通過 基于 MOS場效應的浮栅半導體 實作的底層0,1bit位的互換, 而 機械硬碟則是電信号 磁信号之間的轉化,還夾雜着主流程上大量的機械運動。一個是純化學反應,一個是機械運動為主體,兩者性能當然千差萬别)
- 控制器方面,sata ssd需要通過南僑控制器中轉,再連接配接到CPU;而NVME的 pcie ssd主要可以和CPU直連。是以時延方面,PCIE ssd 更低。
- 軟體接口方面:NVME 縮短了CPU 到ssd的指令路徑,比如NVME減少了對寄存器的通路次數,使用了MSI-X中斷管理;并行&多線程優化 – NVME減少了各個CPU核之間的鎖同步操作。
-
高性能
理論上,IOPS= 隊列深度/IO延遲,所有IOPS的性能和隊列深度有很大的關系(但并不是正比,實際應用中,随着隊列深度的增加,IO延時也會增加)。
SATA ssd 市面上能做到最好的IO深度是32,但目前企業級的PCIE ssd 隊列深度能夠達到128 甚至256才能發揮出其底層ssd的最高性能。 而在NVME标準下,最大的隊列深深度能夠達到64K。
-
低功耗
NVME加入了自動功耗狀态切換 和 動态能耗管理功能。
NVME-CLI nvme工具使用
是以總上來看NVME 是現在新型存儲的标準,是以我們做存儲的應該上通應用,下曉FM,且與時俱進。
而且NVME 社群也維護了一套完整的工具來協助我們加深對NVME的了解NVME-CLI
關于NVME以及 NAND閃存的原理其實了解的非常淺薄,後續會持續補充。接下來回到本節的主題,将NVME的基本工具使用做一個整體的記錄。
1. 安裝
- on ubuntu :
https://github.com/linux-nvme/nvme-cli
- on Centos/RHEL 7.x or 8x
https://github.com/linux-nvme/nvme-cli
2. 指令綜述
注意,以下指令需要在root使用者下運作,并不是所有的自指令,隻是一些比較常用的指令。
建議在測試硬碟上使用,且明确指令的含義,以下的部分指令會删除資料。
Command | Description |
nvme list | 檢視所有連接配接到目前系統的nvme裝置:名稱,序列号,大小,LBA 和 serial |
nvme id-ctrl | 展示nvme 控制器和它所支援的一些特性 |
nvme id-ns | 展示nvme 的命名空間,優化特性和支援特性 |
nvme format | 安全擦除SSD上的資料,格式化LBA大小或保護資訊以實作端到端資料保護 |
nvme sanitize | 安全得擦除SSD上的所有資料 |
nvme smart-log | 檢視NVME的smart log資訊:page的健康狀态,溫度,穩定性情況等 |
nvme fw-log | 檢視NVME的固件日志,會列印每個entry的健康情況 |
nvme error-log | NVME的異常日志 |
nvme reset | 重置NVME的控制器 |
nvme help | 檢視幫助資訊 |
nvme delete-ns | 指定裝置删除一個命名空間 |
nvme create-ns | 指定裝置建立命名空間。比如可以為一個裝置建立一個較小大小的命名空間,進而提升SSD的穩定性,性能和延時?(具體原理還不太清楚) |
nvme fw-download | 為一個裝置下載下傳一個新的固件系統 |
nvme fw-commit | 讓固件立即運作 |
如下使用
nvme help
能夠看到大量的指令集
3. 基本指令示範
一些指令需要指定裝置運作,這裡建議指定字元裝置,即/dev/nvme0 這樣的,因為字元裝置檔案擷取到的資料是直接從底層存儲中取出來的;如果指定/dev/nvme0n1這樣的塊裝置,資料讀取會走作業系統buffer cache,可能有一些資料更新不及時。
-
檢視nvme controller 支援的一些特性nvme id-ctrl /dev/nvme0
NVME Identify Controller:
vid : 0x1c5f # PCIe vendor id
ssvid : 0x1c5f
sn : FL172100442 # serial number
mn : Z45C7032C22
fr : 2090500 # firm version 固件版本号
rab : 1
ieee : 00e0cf
cmic : 0
mdts : 5
cntlid : 0
ver : 0
rtd3r : 0
rtd3e : 0
oaes : 0
...
...
-
檢視目前環境的 nvme裝置nvme list
-
nvme id-ns /dev/nvme0
檢視nvme的namespace,這個能夠非常友善得看到nvme内部的LBA(邏輯位址和實體位址的映射表)使用情況等非常有用的資訊。
如果出現如下錯誤:
# nvme id-ns /dev/nvme0
Error: requesting namespace-id from non-block device
NVMe Status:INVALID_NS: The namespace or the format of that namespace is invalid(b) NSID:0
這裡就需要指定namespace的id了,通過
nvme list-ns /dev/nvme0
檢視目前裝置的name space
# nvme list-ns /dev/nvme0
[ 0]:0x1
然後再執行
nvme id-ns --namespace-id=0x1 /dev/nvme0
即可看到如下資訊
使用-H 指令能夠提升輸出結果的可讀性
-
檢視裝置smart log資訊nvme smart-log /dev/nvme0
-
檢視裝置error 資訊nvme error-log /dev/nvme0
4. NVME 固件裝置更新
ssd 供應商會跟随ssd的研發周期性更新固件,跟進固件的更新能夠保證一些關于bug-fix, 穩定性提升的更新檔包及時得到更新。當然,固件更新的頻率也不會很高,一般一年不會超過5次。更新前可以和供應商核對固件更新的版本資訊。
确認固件版本:
nvme id-ctrl /dev/nvme0 |grep "fr "
下載下傳固件并應用起來
nvme fw-download /dev/nvme0 -
nvme fw-commit /dev/nvme0 -a 0
這裡注意下commit 過程中
-a
指定的action 模式有種,表示不同的含義
- 0 : 下載下傳的固件鏡像替換原有的固件鏡像,但并不會激活。即不會讓這個鏡像運作起來
- 1:下載下傳的固件鏡像替換原有的固件鏡像,會在NVME reset之後運作起來。(發生了熱插拔,斷電,上電也會運作)
- 2:由固件插槽指定的鏡像會在下次重置之後激活
- 3: 擷取到的固件鏡像會被立即激活而不需要重置
下載下傳好的固件,加入需要重置的話可以執行如下指令:
nvme reset /dev/nvme0