什么是 SPDK?
隨著存儲介質(zhì)在 I/O 性能方面不斷演進(jìn),存儲軟件占用的總事務(wù)時(shí)間百分比變得越來越大。提高存儲軟件棧的性能和效率至關(guān)重要。存儲性能開發(fā)套件 (SPDK) 是一個(gè)開源軟件框架,它提供了一組庫和工具,用于根據(jù)特定需求編寫高性能、可擴(kuò)展的用戶模式存儲應(yīng)用。SPDK 全面釋放現(xiàn)代存儲硬件的潛力,例如非易失性存儲器 (NVM) 設(shè)備、固態(tài)硬盤 (SSD) 和網(wǎng)絡(luò)存儲設(shè)備。
SPDK?的工作原理是什么?
傳統(tǒng)的內(nèi)核 I/O 棧由于上下文切換、數(shù)據(jù)復(fù)制、中斷和資源同步等原因帶來了開銷。SPDK?大幅減少了 I/O 處理期間的開銷,其方法如下:
使用存儲應(yīng)用的用戶模式,而非內(nèi)核模式。設(shè)備綁定 UIO 或 VFIO 驅(qū)動(dòng)程序后,SPDK 運(yùn)行用戶空間中的設(shè)備,從而消除了成本高昂的上下文切換。應(yīng)用利用?SPDK 庫,直接通過用戶空間驅(qū)動(dòng)程序與設(shè)備通信。
以輪詢模式而不是中斷模式運(yùn)行。在初始化期間,SPDK 會在每個(gè)核心上創(chuàng)建一個(gè)線程,稱為 ?Reactor(圖 1)。用戶在此 Reactor 上注冊輪詢器來輪詢硬件是否完成,而不是等待中斷。這樣就降低了中斷處理開銷和延遲。
使用無共享線程模型。每個(gè) SPDK 線程都獨(dú)立運(yùn)行自己的一組數(shù)據(jù)結(jié)構(gòu)和資源,從而避免了同步開銷。每個(gè) Reactor 上會創(chuàng)建一個(gè)事件環(huán),以進(jìn)行必要的線程通信。
圖 1:SPDK 線程模型
SPDK 框架
如圖 2 所示,SPDK 包含多層。
圖 2:SPDK 架構(gòu)
硬件驅(qū)動(dòng)程序:快速非易失性存儲器 (NVMe) 驅(qū)動(dòng)程序是 SPDK 的基礎(chǔ)組件。這是一個(gè) C 庫,用于與 NVMe 設(shè)備之間進(jìn)行直接零拷貝數(shù)據(jù)傳輸。virtio 驅(qū)動(dòng)程序允許與 virtio 設(shè)備進(jìn)行通信。
塊存儲:SPDK 提供豐富的后端存儲設(shè)備支持,包括以 NVMe SSD、Linux 異步 I/O (AIO) 作為支持的 NVMe 塊設(shè)備,以便讓 SPDK 能夠與 HDD?和?ceph RBD 等內(nèi)核設(shè)備交互,從而將 ceph 作為 SPDK 的后端設(shè)備。
塊存儲服務(wù):SPDK 塊存儲服務(wù)層為附加客戶功能提供靈活的 API,這些功能包括?RAID?和塊層壓縮。
塊存儲協(xié)議:塊存儲協(xié)議使得 SPDK 能夠通過不同的傳輸協(xié)議將其后端存儲提供給遠(yuǎn)程客戶端、虛擬機(jī)或其他進(jìn)程。iSCSI target 是在 TCP/IP 連接上實(shí)現(xiàn)了傳輸塊級 SCSI 數(shù)據(jù)的既定規(guī)范。NVMe over Fabrics (NVMe-oF) target 是 NVMe-oF 規(guī)范在用戶空間的一個(gè)實(shí)現(xiàn),即在網(wǎng)絡(luò)上呈現(xiàn)一個(gè)快設(shè)備。Vhost target 使得 SPDK 能夠?yàn)榛?Qemu 的虛擬機(jī)或 Kata 容器提供后端存儲。Vfio-user 允許 SPDK 將虛擬的 NVMe 設(shè)備提供給虛擬機(jī),后者利用現(xiàn)有的 NVMe 驅(qū)動(dòng)程序與設(shè)備進(jìn)行通信。
文件存儲服務(wù):SPDK 在其塊分配器 Blobstore 上還提供了一個(gè)名為 BlobFS 的文件系統(tǒng)。它可作為?MySQL?和?Rocksdb?的存儲后端,從而使整個(gè) I/O 路徑都位于用戶空間中。
什么是 NVMe over TCP?
NVMe 是一種專為 SSD 而設(shè)計(jì)的協(xié)議,旨在通過 PCIe 接口來顯著提高性能。NVMe over PCIe 是 NVMe 協(xié)議的初期目標(biāo),用于本地 NVMe SSD 訪問。它通過 PCIe 接口協(xié)議將命令和響應(yīng)映射到主機(jī)的共享內(nèi)存,以此來傳輸數(shù)據(jù)。
NVMe-oF 支持通過網(wǎng)絡(luò)來遠(yuǎn)程共享和訪問 NVMe 存儲設(shè)備,例如以太網(wǎng)或光纖通道。NVMe-oF 是?NVMe over PCIe 的擴(kuò)展。NVMe-oF 利用基于消息的模型或組合模型在主機(jī)與目標(biāo)存儲設(shè)備之間通信。所支持的傳輸協(xié)議包括光纖通道 (Fibre Channel)、RDMA (Infiniband、ROCE、iWARP) 和 TCP(圖 3)。
圖 3:NVMe over Fabrics 模型
SPDK 支持 RDMA、TCP 和光纖通道傳輸。它由 initiator 程序框架和 target 組成(圖 4)。如果 initiator 程序(主機(jī))和 NVMe SSD 位于同一服務(wù)器內(nèi),則直接通過 PCIe 訪問設(shè)備。否則,啟動(dòng)程序必須通過結(jié)構(gòu)來訪問遠(yuǎn)程目標(biāo)設(shè)備。
圖 4:SPDK NVMe over Fabrics 框架
在多種結(jié)構(gòu)選項(xiàng)中,NVMe over TCP 允許用戶跨標(biāo)準(zhǔn)以太網(wǎng)使用 NVMe。得益于成熟 TCP/IP 棧的穩(wěn)定性和可移植性,這可實(shí)現(xiàn)更低的部署成本,并降低設(shè)計(jì)復(fù)雜性。
我們將重點(diǎn)關(guān)注 SPDK NVMe over TCP,它集 NVMe over TCP 和 SPDK 工作機(jī)制的優(yōu)點(diǎn)于一身。?
使用 TCP 傳輸時(shí)(圖 5),每個(gè)主機(jī)端 NVMe 隊(duì)列對都有一個(gè)對應(yīng)的控制器端隊(duì)列對,后者被映射至自己的 TCP 連接。該 NVMe 隊(duì)列對將會分配給單獨(dú)的 CPU 核心。命令包 (Command Capsules) 被封裝到 TCP 協(xié)議數(shù)據(jù)單元 (PDU) 中,并通過 Linux 系統(tǒng)調(diào)用(包括?sendmsg),經(jīng)標(biāo)準(zhǔn) TCP/IP 套接字發(fā)送出去??刂破鞫藦奶捉幼志彌_區(qū)讀取接收到的數(shù)據(jù)并構(gòu)建接收 CMD 包。這其中就包括用于進(jìn)一步處理的請求信息。處理完請求后,會生成一個(gè) RSP 包并通過套接字發(fā)送出去。響應(yīng)數(shù)據(jù)到達(dá)主機(jī)端套接字緩沖區(qū),該緩沖區(qū)已被封裝到接收 CMD 包中。
圖 5:NVMe over TCP 數(shù)據(jù)路徑
Arm 平臺上的優(yōu)化工作
SPDK NVMe over TCP 是一個(gè)高性能解決方案,它通過 TCP/IP 網(wǎng)絡(luò)將 NVMe 存儲提供給遠(yuǎn)程客戶端。雖然 SPDK 是無鎖的,并且 NVMe 驅(qū)動(dòng)程序位于用戶空間內(nèi),但基于內(nèi)核的 TCP/IP 棧并不是無鎖的。因此,內(nèi)核與用戶空間之間的系統(tǒng)調(diào)用和內(nèi)存復(fù)制是不可避免的。為了有效利用 TCP/IP 棧,SPDK 引入了多項(xiàng)優(yōu)化,包括:
批量寫入
管道緩沖
零拷貝
我們的優(yōu)化工作基于現(xiàn)有的實(shí)現(xiàn),旨在進(jìn)一步提高 SPDK NVMe over TCP 性能:
調(diào)整系統(tǒng)配置
改進(jìn)數(shù)據(jù)局部性
平衡零拷貝和非零拷貝
減少功耗浪費(fèi)
配置優(yōu)化
正確的系統(tǒng)配置對于 SPDK 來說至關(guān)重要。平臺會根據(jù)架構(gòu)和功能進(jìn)行配置,包括:
Linux 內(nèi)核設(shè)置
PCIe 參數(shù)
NIC 參數(shù)
Linux 內(nèi)核命令行設(shè)置
Hugepage:SPDK 依賴于數(shù)據(jù)平面開發(fā)套件 (DPDK)?庫來管理組件,包括大內(nèi)存頁和緩沖池。DPDK 支持 2MB 和 1GB,以涵蓋大內(nèi)存區(qū)域,同時(shí)不會出現(xiàn)過多 TLB 未命中的情況,從而提供更好的性能。
核心隔離:將 CPU 與內(nèi)核調(diào)度程序隔離開,以減少上下文切換。
Iommu.passthrough:如果 IOMMU 可用,SPDK 建議使用?vfio-pci 驅(qū)動(dòng)程序。否則,請使用?uio_pci_generic 或 igb_uio。要使用?uio_pci_generic 或 igb_uio 驅(qū)動(dòng)程序,應(yīng)禁用 IOMMU 或?qū)⑵湓O(shè)為直通模式。如果未設(shè)置 iommu.passthrough,vfio-pci 驅(qū)動(dòng)程序?qū)?DMA 使用 I/O 虛擬地址 (IOVA)。這對于?IOMMU 的轉(zhuǎn)換更為安全。如果在 GRUB 命令行中添加“iommu.passthrough=1”,則對 DMA 使用物理地址。這樣可以提高性能。
例如,對于四個(gè)?1G 的大頁,請將以下參數(shù)添加到 GRUB 命令行中。SPDK 運(yùn)行在 CPU 核心 0-7 上,而 IOVA 為物理地址。
PCIe 參數(shù)調(diào)整
PCIe 最大有效負(fù)載大小 (PCIe Max Payload Size) 決定了 PCIe 數(shù)據(jù)包的最大大小。制造商會設(shè)置最大 TLP 有效負(fù)載大小,該值還取決于所連接的設(shè)備。將“pci=pcie_bus_perf”添加到內(nèi)核命令行,以確保使用 PCIe 最大有效負(fù)載大小。
PCIe 最大讀取請求 (PCIe Max Read Request) 決定了所允許的最大 PCIe 讀取請求。PCIe 最大讀取請求的大小可能會影響待處理請求的數(shù)量。請根據(jù)工作負(fù)載進(jìn)行調(diào)整。
使用以下命令設(shè)置最大請求大?。?/p>
NIC 參數(shù)調(diào)整
NIC 隊(duì)列數(shù)和隊(duì)列深度
通常情況下,NIC Rx/Tx 隊(duì)列數(shù)的設(shè)置與 CPU 數(shù)量相同。隊(duì)列大小需要適當(dāng),因?yàn)檩^小的隊(duì)列可能會導(dǎo)致數(shù)據(jù)包丟失。如果環(huán)的大小超過了緩存,則較大的隊(duì)列可能會導(dǎo)致緩存利用率較差。請根據(jù)系統(tǒng)資源和工作負(fù)載進(jìn)行調(diào)整。
硬中斷關(guān)聯(lián)
IRQ 關(guān)聯(lián)是一項(xiàng) Linux 功能,它會將一些 IRQ 分配給專用處理器。正確的 IRQ 關(guān)聯(lián)設(shè)置可提高服務(wù)器工作效率。對于大多數(shù)情況而言,NIC 的 IRQ 應(yīng)綁定至 NIC 所在的同一 NUMA 節(jié)點(diǎn)。Irqbalance 是一個(gè) Linux 守護(hù)進(jìn)程,它有助于平衡所有 CPU 之間的中斷所產(chǎn)生的 CPU 負(fù)載。要設(shè)置 IRQ 關(guān)聯(lián),應(yīng)首先停止 irqbalance 服務(wù)。
例如,在 64 核系統(tǒng)的上層 32 核上,請將以下命令用于 IRQ 40:
硬中斷合并
中斷合并[1]是一種控制設(shè)備何時(shí)引發(fā)中斷的方法。在產(chǎn)生中斷之前,NIC 會收集入站數(shù)據(jù)包并等待達(dá)到特定閾值。這樣便減少了 CPU 必須處理的總中斷數(shù),從而導(dǎo)致吞吐量提高、延遲增加以及 CPU 使用率降低。
請使用以下命令啟用自適應(yīng) irq 合并:
根據(jù)用例,使用?ethtool -C 設(shè)置 irq 合并:
參數(shù)為:
rx-usecs:在數(shù)據(jù)包到達(dá)后會延遲 RX 中斷的?usecs?數(shù)量
rx-frames:在 RX 中斷之前所接收到的最大數(shù)據(jù)幀數(shù)
rx-frames-irq:在主機(jī)處理中斷時(shí),在生成 RX 中斷之前所接收到的最大數(shù)據(jù)幀數(shù)
軟中斷合并
NAPI[2] 是一種減少網(wǎng)絡(luò)設(shè)備在數(shù)據(jù)包到達(dá)時(shí)所生成的 IRQ 數(shù)量的機(jī)制。它會注冊一個(gè)輪詢函數(shù),NAPI 子系統(tǒng)調(diào)用此函數(shù)可收集數(shù)據(jù)幀。
設(shè)置“net.core.netdev_budget”和“net.core.netdev_budget_usecs”可限制在一個(gè) NAPI 輪詢周期內(nèi)輪詢的數(shù)據(jù)包數(shù)量。Netdev_budget 是在一個(gè)輪詢周期內(nèi)從所有接口獲取的最大數(shù)據(jù)包數(shù)。即使 netdev_budget 尚未耗盡,輪詢周期也不得超過 netdev_budget_usecs 微秒。而?dev_weight 是內(nèi)核在 NAPI 中斷上可以處理的最大數(shù)據(jù)包數(shù),它是一個(gè) Per-CPU 變量。
請參閱?Linux 網(wǎng)絡(luò)性能參數(shù)[3],獲取更多信息。
TCP 套接字緩沖區(qū)
默認(rèn)情況下,TCP 套接字緩沖區(qū)大小是根據(jù)系統(tǒng)內(nèi)存自動(dòng)計(jì)算的。較小的套接字緩沖區(qū)可能會導(dǎo)致接收數(shù)據(jù)時(shí)丟包,以及發(fā)送數(shù)據(jù)時(shí)頻繁寫操作阻塞。要調(diào)整緩沖區(qū),請使用以下命令:
數(shù)據(jù)局部性優(yōu)化
在 TCP 內(nèi)核空間中,當(dāng)數(shù)據(jù)到達(dá) NIC 且 NIC DMA 數(shù)據(jù)包到達(dá) RAM 時(shí),會根據(jù) RSS 中的哈希函數(shù)選擇一個(gè)接收環(huán)。數(shù)據(jù)包的引用被排入環(huán)形緩沖區(qū)中。系統(tǒng)會發(fā)起硬 IRQ,由 CPU 負(fù)責(zé)處理。如果設(shè)置 IRQ 綁定,則是所分配的 CPU,否則 irqbalance 服務(wù)會選擇一個(gè)。默認(rèn)情況下,軟 IRQ 會在與硬 IRQ 相同的 CPU 核心上觸發(fā);硬 IRQ 會觸發(fā) NAPI,以從接收環(huán)形緩沖區(qū)輪詢數(shù)據(jù)。該數(shù)據(jù)包的處理是在?CPU 核心中進(jìn)行的,直到被排入套接字接收緩沖區(qū)中。
在 SPDK NVMe over TCP 中,每個(gè)來自客戶端的連接在啟動(dòng)期間都會分配給一個(gè) Reactor(CPU 核心)。此連接的套接字讀/寫是在該 CPU?核心上完成的。所以,內(nèi)核空間與用戶空間之間存在語義差距,這與?CPU 核心親和性有關(guān)。
為了保證 CPU 核心處理內(nèi)核空間中的此套接字?jǐn)?shù)據(jù)與用戶空間中讀取此套接字的核心 (SPDK) 完全相同,在 SPDK NVMe over TCP 中,我們引入了基于 CPU 親和性的套接字處理[4]?。它將獲取套接字的 CPU 親和性,并確定在連接啟動(dòng)期間應(yīng)將此套接字分配給哪個(gè) CPU 核心。例如,當(dāng)新連接(套接字 A)啟動(dòng)時(shí)(圖 6),我們會獲得套接字 A 的 CPU 親和性。這里是?CPU 核心 1,它負(fù)責(zé)該套接字?jǐn)?shù)據(jù)包的內(nèi)核空間處理。然后在 SPDK 中,套接字 A 會被分配給核心 1 中的輪詢組,以后套接字 A 的讀/寫將會在核心 1 上執(zhí)行。
圖 6:TCP 數(shù)據(jù)接收流程
例如:對于六個(gè) P4600 NVMe 盤的服務(wù)器,它使用八個(gè)核心,NIC IRQ 被綁定至這八個(gè)核心,而客戶端程序使用 24 個(gè)和 32 個(gè)核心。這個(gè)優(yōu)化使隨機(jī)寫入性能提升 11% - 17%。
零拷貝優(yōu)化
對于使用套接字發(fā)送數(shù)據(jù)時(shí),MSG_ZEROCOPY[5]?標(biāo)記可以使能零拷貝。該功能目前主要針對 TCP 套接字實(shí)現(xiàn)。然而,零拷貝并不是沒有代價(jià)的,因?yàn)樗鼤陧撁婀潭ㄆ陂g導(dǎo)致額外的頁面記錄和完成后通知的開銷。
在 SPDK NVMe over TCP 中,零拷貝可以在啟動(dòng)期間進(jìn)行啟用或禁用。啟用后,不論大小,所有數(shù)據(jù)均通過零拷貝發(fā)送。這對于小數(shù)據(jù)(例如回復(fù)請求)的性能有負(fù)面影響。因此,平衡內(nèi)存復(fù)制開銷與頁面固定開銷至關(guān)重要。動(dòng)態(tài)零拷貝[6]的引入是為了設(shè)置數(shù)據(jù)發(fā)送的閾值,以確定是否通過零拷貝發(fā)送數(shù)據(jù)。任何大于閾值的數(shù)據(jù)由零拷貝發(fā)送,其他數(shù)據(jù)則不然。
例如,?在 16 個(gè) P4610 NVMe SSD、兩個(gè)客戶端,且客戶端與服務(wù)器端程序的配置與?SPDK 報(bào)告[7]相同的測試環(huán)境中,對于 posix 套接字 rw_percent=0 (randwrite),經(jīng)測試,128 隊(duì)列深度、服務(wù)器端 1 至 40 個(gè) CPU 核心下的性能提升可達(dá) 2.4% - 8.3%。當(dāng)讀取百分比大于 50% 時(shí),其影響并不明顯。對于 uring 套接字 rw_percent=0 (randwrite),經(jīng)測試,128 隊(duì)列深度、服務(wù)器端 1 至 40 個(gè) CPU 核心下的性能提升可達(dá) 1.8% - 7.9%(圖 7)。當(dāng)讀取百分比大于 50% 時(shí),性能提升可達(dá) 1% - 7%。
圖 7:qdepth=128 時(shí)的 4KB 隨機(jī)寫入性能
功耗優(yōu)化
以前在 SPDK 中,無論要處理的工作負(fù)載數(shù)量如何?,CPU 核心上的每個(gè)線程都工作在輪詢模式下。然而,如果工作負(fù)載隨時(shí)間變化較大,可能會造成功耗浪費(fèi)。為了解決這個(gè)問題,我們引入了動(dòng)態(tài)調(diào)度程序框架,以實(shí)現(xiàn)節(jié)能并降低 CPU 占用率。
調(diào)度程序框架會動(dòng)態(tài)收集每個(gè)線程和 Reactor 的數(shù)據(jù),并執(zhí)行包括移動(dòng)線程、切換 Reactor 模式和設(shè)置 CPU 核心頻率等在內(nèi)的操作。例如,如果 Reactor 1 到 Reactor N 中的輪詢器空閑,則相應(yīng)的 SPDK 線程將遷移至 Reactor 0(圖 8)。然后,Reactor 1 至 Reactor N 切換至中斷模式。Reactor 0 的 CPU 頻率會根據(jù)該 Reactor 的繁忙程度進(jìn)行調(diào)整。我們將這稱之為?CPU 頻率調(diào)節(jié)。
圖 8:SPDK 動(dòng)態(tài)調(diào)度程序解決方案
Linux 內(nèi)核通過 CPU 頻率調(diào)節(jié) (CPUFreq) 子系統(tǒng)支持 CPU 性能調(diào)節(jié)。它由三個(gè)模塊組成:
核心
調(diào)節(jié)調(diào)控器
調(diào)節(jié)驅(qū)動(dòng)程序
調(diào)節(jié)驅(qū)動(dòng)程序與硬件通信。cppc_cpufreq 驅(qū)動(dòng)程序適用于大多數(shù) AArch64 平臺。該驅(qū)動(dòng)程序使用 ACPIv5.1 規(guī)范中所述的協(xié)作處理器性能控制 (CPPC) 方法。CPPC 是以 CPU 性能值的抽象連續(xù)量表為基礎(chǔ)的。這樣就允許遠(yuǎn)程功耗處理器靈活地進(jìn)行優(yōu)化,以提高功率和性能。
為了啟用 AArch64 上的 CPU 頻率調(diào)節(jié),cppc_cpufreq 驅(qū)動(dòng)程序支持[11]被添加到? DPDK Power Library(DPDK 功率庫)中。SPDK 利用它來調(diào)節(jié) CPU 頻率,也利用它來獲取頻率信息供調(diào)節(jié)使用。選項(xiàng)包括 highest_perf、nominal_perf?以及?scaling_max_freq、scaling_min_freq?等等。它為用戶提供了?API,用于設(shè)置 CPU 頻率和啟用或禁用加速技術(shù)。請參閱?DPDK Power Library[12],獲取有關(guān) API 的更多信息。
結(jié)論
本文介紹了?SPDK、SPDK NVMe over TCP 以及如何對其進(jìn)行優(yōu)化,其中包括系統(tǒng)配置優(yōu)化、數(shù)據(jù)局部性優(yōu)化、內(nèi)存零拷貝優(yōu)化和功耗優(yōu)化。它們可用于解決對性能至關(guān)重要的存儲問題。
審核編輯:劉清
-
以太網(wǎng)
+關(guān)注
關(guān)注
41文章
5635瀏覽量
175950 -
SSD
+關(guān)注
關(guān)注
21文章
2984瀏覽量
119600 -
TCP
+關(guān)注
關(guān)注
8文章
1402瀏覽量
81048 -
固態(tài)硬盤
+關(guān)注
關(guān)注
12文章
1542瀏覽量
58645 -
非易失性存儲器
+關(guān)注
關(guān)注
0文章
109瀏覽量
23714
原文標(biāo)題:在 Arm 平臺上進(jìn)行 SPDK NVMe over TCP 優(yōu)化
文章出處:【微信號:Arm社區(qū),微信公眾號:Arm社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
評論