作者簡介
唐傑上次拋出了磚,冬瓜哥的玉來了!
冬瓜哥,《大話存儲》系列圖書作者,現任Microsemi存儲系統架構師
想要和冬瓜哥還有全世界的大牛討論SSD及存儲相關技術?加nanoarch為微信好友,拉你進ssdfans微信群
唐傑忠是誰?唐傑忠是我國著名相聲演員,先後與馬季和姜昆合作。那麼,唐傑又是誰? 唐傑現任賽靈思(Xilinx)數據中心架構師,和冬瓜哥的Title是一樣的,真是門當戶對啊。鑑於老唐的長相不太好貼上來怕嚇壞各位,冬瓜哥的也一樣對不起觀眾,所以就不貼照片了。
事情的起因是這樣的,在ssdfans群裡,冬瓜哥和往常一樣在幫助大家回答問題。在回答一個SSD上文件系統mount的參數的問題時,按照唐傑的說法「俺不知深淺地插了一句嘴,該打。然後就為了拍瓜哥一個馬屁,就說瓜哥應該寫一個SSD性能測試的指導,結果瓜哥說自己不是專業人士不能寫,俺又不明就裡地說俺可以寫一個」。冬瓜哥一看唐傑這老哥們挺能裝逼的,於是壯了壯膽,順嘴來了一句:「如果唐總寫了,鄙人就也寫一篇作為回應」,結果唐傑這哥們還真寫了,40分鐘之後,這老哥竟然發了個word文檔到群裡,並自稱「快槍手」,哎呦我擦,這哥們逼格彰顯啊!冬瓜哥既然有言在先,那就得接這個大招了。唐總把自己的文章稱為磚,說是想以此拋磚引冬瓜哥的玉。
結尾,唐總還沒忘了裝個逼,其聲明了「在談這個具體內容之前,俺要強調,俺的磚全是腦中所記,因為不方便上網,而且也是磚,就比較散漫,寫到哪裡算哪裡了」。哎呦,這簡直就是在暗示冬瓜哥說:你小子如果敢去網上參考一堆資料,那就是沒逼格! 行嘞,冬瓜哥當然不用去網上參考,這一點可以保證,下面的回應文字都是冬瓜哥直接腦出。冬瓜哥就佩服直接腦出的人,因為腦出需要足夠的積累和邏輯思維,對於那些拿著別人做好的ppt每走一頁加上點文字再走一頁的,噗~~。
好了,冬瓜哥這就來和唐總說個相聲!。文中黑色字體是唐總原文,藍色字體是冬瓜哥的文字。
-唐總文章開始-
工具篇:
Fio 目前最常用的性能測試工具,主要是linux下。這個工具是目前我用過的最能生成IO請求的工具。Fio可以用比較小的代價在短時間能生產IO,這個能力的確沒有其他工具可以比。因此文中預設的測試工具就是它了。
Vdbench:SUN遺留下來的工具,因為基於Java,他的可移植性比fio好,同時支持壓縮和dedup的測試,因此也是企業測試的首選。
Iometer:Windows平臺為主,因為是gui的,因此腳本化比較難,之前windows比較流行的時候,用的多,現在在數據中心就呵呵了。
SQLIO和orion都是資料庫廠商的工具,主要測試8K的隨機I/O和1M的順序I/O,是DBA的最愛,作為SSD性能狗必須跪舔。
Sysbench因為可以測試MySQL,也是新貴的最愛,要知道霸爺到ali的第一個blog就是sysbench.
Workload篇:
I/Osize: 4K 是主流,8K是MSSQL和Oracle,16K是MysqlInnodb。
QueueDepth:這個預設是32,因此目前的SSD,特別是SATA的SSD,NCQ是32,因此不能太少。唐總,這個地方您老的逼格應該深入發揮一下才是啊,可能是為了追求快搶快射而省略了吧,鄙人就幫您老補充補充吧。SATA盤上的Queue Depth的確是32,對於固態盤來講32的確太低,這個沒辦法。但是,內核IO協議棧裡的QD可並不是說必須與SATA盤上的QD匹配且就算再大也沒用。每一層的QD其實是獨立的,因為這些層次間的Queue都是異步聯動的。比如如果內核裡QD=SATA盤NCQ的Depth=32,那麼一旦Host端運行的線程較多,在IO線程之間穿插了不少計算線程的話,那麼很有可能會出現內核隊列被充滿後,線程輪轉到計算線程,期間又被消耗空並且持續為空一段時間的情況,從而導致吞吐量瞬時下降。如果內核QD調節為比如256,那麼就可以在計算線程運行期間在隊列中繼續保有IO,維持底層的吞吐量。也就是說,隊列深度越高,讓底層吞吐量持續平穩的機率越大,當然這都得看上層應用的環境,多少個IO線程,每個IO多少個outstanding io depth等。
隨著隊列長度的增加,吞吐量不斷上升到一個極限便保持不變,達到了底層的最大並發度;而IO平均時延則加速上升,
大到一定程度之後,遠超過底層的吞吐量極限,此時吞吐量保持不變,IO平均時延則線性上升(以每個IO時延的0.5倍為步進累積)。排隊能夠讓底層充分的並發,不管是物理並發(真的有多條路)還是邏輯並發(只有一條路但是是流水線處理方式),代價就是平均時延上升。在《【冬瓜哥手繪】IO時延你被騙了多久》一文中,大家可以看到單筆IO的時延是固定的,多筆IO排隊之後,隨著隊列長度加長,平均時延就會上去,其消耗在了等待時間上,而執行時間是不變的。
Numjobs:生成I/O的engine的數量,如果thread=1就是幾個線程,否則就是進程,建議線程。Numjobs可以等於CPU的core就行,不算HT。
Numjobs和Queue Depth定義了I/O的workload的壓力,基本上是 fio numjobsXQD = vdbench的thread。唐總,謝謝哈!這裡您老又留給冬瓜哥裝逼的機會了,您老應該自己裝才對啊,這樣冬瓜哥就很難接招了。這裡有個很明顯的疑問,到底是用更多的線程數量而每個線程的QD或者叫Outstanding IO數量少一些呢,還是用更少的線程數量但是每個線程發出多一些的Outstanding IO呢?兩者相乘的總QD是一樣的,如何選擇呢?這得從內核協議棧的隊列數量說起。Linux老內核裡的SCSI協議棧裡為每個塊設備只維護了一個總隊列,位於塊層,由IO Scheduler負責入隊,當然IO Scheduler上方會維護多個子隊列以供接收多個進程的IO然後再以對應的策略向總隊列中入隊。最終的總隊列深度在256附近。所以,多個線程會將IO入隊到同一個隊列,此過程就必須加鎖,線程數越多,相對鎖效率越低;另外,加鎖的變量會在多個CPU核心的緩存內形成桌球效應,因為每次更改某個變量會導致對應緩存行變為M(Modified)狀態,同時會有一筆廣播發送到其他核心將對應緩存行改為I(Invalid)狀態,其他核心搶鎖時,該緩存行會從M態的緩存轉發給I態的緩存並將兩邊同時改為S(Share)態,過程很耗時間。所以多CPU晶片間的桌球效應會導致更高的時延。綜上所述,用少量線程同時每個線程outstanding io數量較多這種方案更好。
I/O 引擎: 基本上是libaio,這個是衝IOPS的,對於延時為主的測試,建議psync。嗯,唐總說的好,但是唐總顯然是故意又留了讓冬瓜哥裝逼的機會。說到同步和異步IO,這裡有個高逼格的知識可能不少人不知道。冬瓜哥就給來說道說道。異步IO為什麼能衝IOPS,就是因為兩個原因:IO路徑是異步流水線化的、IO路徑上也有物理並發的。前文中提到過,流水線並不能降低時延,其只能增加邏輯並發量。當然,如果上層某筆操作底層被分割為多筆操作,那麼這多筆操作如果並發執行,結果就會體現為該上層操作的時延降低對應的倍數,相對於非流水線處理來講。不過對於底層的IO來講,該規則不適用,底層一筆IO分隔開並發執行相比不分割,其效果幾乎沒有差別。為什麼唐總說如果測時延或者保證時延最低要用同步IO方式呢,因為單線程同步IO可以保證IO路徑被該IO獨佔,沒有排隊,上文中也說到了排隊會以0.5倍固有時延步進抬升。所以,如果你的應用只能發出同步IO,那麼對不起,IO路徑上的並發度的效果將蕩然無存,沒有用,增加同步IO場景的性能,只能通過降低時延的方式,將協議棧變短變薄,底層最好直接用SSD。這就是很多系統在壓測時候表現彪悍,但是實際場景下慘不忍睹的一個最關鍵原因,時延太高。
DirectI/O: 這個是本地測試標配,但是要注意網絡I/O可能只支持buffer I/O。唐總,NFS路徑也是可以DirectIO的。Direct IO可以繞過系統page cache,避免一些由於IO不對齊導致的效率問題,以及降低在不命中時的時延。通常使用DIO的應用自身會在用戶態維護緩存,page cache這點效果不會增加多少效果,反而增加了時延。
隨機順序和IO比例方面:
1. 測試建議先做隨機,再做順序,因為順序可能有cache的影響。先做寫,再做讀,因為SSD的特性,寫入量大之後會性能下降。
2. I/O讀寫比例,資料庫基本是7:3, 9:1, 對於網絡存儲,建議的比例是5:5
文件系統篇:
1. Ext2無視,基本上是ext3和ext4。預設的格式化流行,如果基於md,要考慮I/O的對齊問題。
2. Mount的時候,不管XFS,EXT3/4都建議noatime,noadirtime和nobarrier。Discard這東西還是免了,真心不知道trim的用處。冬瓜哥來解釋一下這些參數。noatime和noadirtime就是當應用訪問文件或者目錄的時候(包括Open( )/Read( )/Write( )等),文件系統會更新對應文件/目錄的訪問時間(access time,atime),這兩個參數就是關閉這個步驟,從而降低訪問時延。唐總,為啥你會說不知道Trim的用處呢,Trim能讓SSD釋放出更多空塊,會提升寫性能啊。不過Trim是否打開並不影響讀寫IO速度,但是會影響刪文件、截斷(Truncate)文件的速度。Barrier的意思就是屏障,有些應用為了保證數據的時序一致性,會在關鍵時刻點把之前已經下發的但是還在緩存中並未刷盤的IO強制刷下去之後,再發出關鍵的一筆IO,該IO必須在之前的所有IO完成後才可以刷盤,否則由於底層的的緩存以及非原子性操作,很有可能出現該IO刷了盤而其他IO沒刷盤之前系統掉電的情況,此時底層系統IO時序不一致。所以Barrier操作底層對應了大量的write through模式的寫IO,以及IO形成順序化提交,具有了同步IO的特徵,同步IO模式無法發揮出系統的吞吐量。
3. 其他的,在測試文件系統的時候,要注意在寫入的時候會有鎖的問題,因此建議使用nrfiles來生成多個文件。如果是單純的覆蓋寫,不需要鎖,誰寫了算誰的,FS不會在這個層面加鎖,只有對元數據操作的時候需要加鎖,比如擴充/截斷了文件的長度等等。對覆蓋寫操作的鎖需要由應用顯式的來調用lock()、lockfile()等功能。
作業系統篇:
1. 對於基於SATA的SSD,對於block層的修改是必須的,必須參考之前LSI nytro的推薦,基本上是:
a) 增大queue的深度
b) Disable預讀
c) Disable和隨機發生器的關係
唐總,什麼是「隨機發生器」?這是哪家的黑科技啊。
d) 還有就是IO affinity, 建議使用的配置是使用生成I/O請求的CPU來響應I/O,降低context 切換的影響。
2. 比較懶的可以用RHEL的tuned-adm來設置。
3. 這裡還有一個就是作業系統的I/O監控:
a) Iostat–dmx /dev/sda 1 這個是必須的命令
b) Mpstat–P ALL 1, 看CPU的使用情況,如果都在softirp,說明你I/O生成有問題,使用numactl來控制。如果都在iowait,說明你的I/O設備的確不行。如果都在sys,說明跑的很正常。不可能都在user,因為fio的I/O請求的數據直接就丟掉了,不可能有usr。
冬瓜哥給大家普及普及。softirp表示軟中斷,出現在IO完成處理的下半部分。硬中斷和軟中斷相當於中斷處理流程上的兩步流水線,第一步要求中斷服務程序很迅速的響應外部硬體的硬中斷,第二步則由中斷服務程序調用下遊的處理邏輯繼續處理該中斷的後續步驟,這就是softirq,後臺異步的處理IO完成流程。softirq是目前多數高速外部IO設備,包括網卡的慣用方式之一,也就是不可避免的必須有。但是如果softirq只在一個cpu上執行,性能就比較差,可以使用IPI(Inter Processor Interrupt)也就是處理器間中斷的方式向其他CPU派發軟中斷,從而達到並發執行。所以唐總說的「如果都在softirq」可能是想說「如果softirq都集中在某個cpu」。但是這並不是IO生成有問題,而是中斷服務程序處理的不高效,是接收端的事情。至於「用numactl來控制」,冬瓜哥就納悶這個場景下與numactl有什麼關係了。期待唐總再寫個文章說道說道。
其他,iowait表示線程發出IO請求之後被阻塞掛起的情況佔了多少比例,這個比例越高,證明底層設備越遲遲無法返回IO,時延太高。sys高說明當前在運行的應用發出大量的系統調用(對外部設備利用比較多)而自己卻沒幹多少事。usr高則相反,自己很勤勞的在計算基本上不去麻煩OS提供的功能,這是個好事情。
c) 高級一點的,可以用perf top看看系統調用的時間,如果都在spinlock上,說明你的IO文件有互斥了。
spinlock證明多個線程在搶鎖,存在衝突的共享資源而且頻繁訪問。但是唐總所說的」說明你的IO文件有互斥了」就讓冬瓜哥不理解了,如果多線程同時範根同一個文件還加鎖,這種鎖並不是spinlock,而是通過lockfile(), lock()這類調用對文件或者字節加鎖,FS加鎖之後,是個穩定態,被排他的線程收到鎖衝突返回後,一般會被設計為等待一段時間再發起open,write, read,或者lock調用,而不是spinlock,spinlock誰啊,讀寫文件是系統調用。除非多個線程自己搞了個共享變量,這可以spinlock。
硬體系統篇:
1. BIOS裡面,CPU的C states是必須disable,測性能,省毛電。唐總,最終線上的話,不還是得考慮省電麼,不看最終應用場景的測試不都是耍流氓麼,就像您老說的「一定要上應用,這個是對自己和公司負責的行為」,所以這個C States鄙人覺得就別動了。
2. HT也是要關的,但是在NVME SSD中,HT貌似不錯,請自行研究。唐總賣了個關子,也不知道是深藏不露,還是虛張聲勢。冬瓜哥也不知道HT對SSD場景的影響所在,這個非常底層,HT是單個核心內部存有兩套線程上下文資源,可以用同一個核心將兩個線程的機器碼穿插交織的執行以充分利用流水線。至於哪種場景在機器碼方面更利於交織,冬瓜哥相信唐總也是說不清楚的:)。
3. VT之類,都是必須關的。Dell/HP/IBM都有BIOS推薦的設置。
4. NUMA,這東西對於性能真心沒好處,還是一點要避免。BIOS能關就關,不能關的話,用numactl來指定吧。如果在BIOS裡disable NUMA,那麼OS將不會感知到底層的CPU/RAM拓撲,內存分配將按照原有方式分配。同時,目前多數伺服器是這麼實現的:BIOS裡關閉NUMA除了會在ACPI表中向OS通告當前系統並不是NUMA架構之外,還會在底層硬體的地址映射電路上對內存地址做interleave,也就是OS分配的比如1MB空間,會被按照緩存行為粒度被條帶化到系統的多個NUMA node掛接的物理RAM裡,也就是底層強制對OS看到的內存空間做條帶化,條帶深度是一個cache line,以便均衡OS對RAM的分配。這樣做的目的是防止OS順序分配內存時這些被分配的空間全部擠在一個CPU晶片所掛接的RAM裡而導致性能不佳。但是,任何性能問題,都不是某個點優化一下就可以解決的,都是要全局配合的。有些應用抱怨說開了NUMA性能反而下降了,兩個原因,要麼沒精細的定製好策略,要麼就是應用的線程和內存訪問形式的確不適合NUMA,但是冬瓜哥感覺後者這個原因是個悖論,即使關閉了NUMA,NUMA架構依然是存在的,只不過方式是如上文所述的那樣去分配內存,那麼也就是說,即使打開NUMA,通過numactl來制定對應的策略,依然可以實現如關閉NUMA類似的效果。所以,別怨NUMA不行,是你自己不行,或者說懶得弄。資料庫類程序都推薦關閉NUMA的原因是因為默認情況下打開NUMA之後OS會給每個進程的內存分配到該進程運行的CPU掛接的RAM,容易導致擁擠從而swap,性能下降。關閉NUMA之後,底層硬體對所有地址做條帶化,系統內所有RAM得到均衡的利用,降低了swap的負面效果,代價則是訪存時延並不是那麼好了,但是對吞吐量影響不算大,當然這也這取決於應用的訪存模式,緩存命中率,讀還是寫等一系列因素。
5. 還有就是硬體的中斷,不要用irqbalance,一定要用irq_affinity來做mask。irqbalance是個後臺進程,通過對系統核心softirq派發模塊動態配置而動態的實現中斷均衡。調節irq_affinity那就是全手動靜態配置了。
6. 對於PCIE slot,儘可能讓兩個設備在不同的CPU上,用taskset,或者numactl來進行分離。NVMe協議棧和底層驅動以及NVMe設備天然支持中斷綁定,這樣可以節省很多跨CPU晶片間流量。
最後一點,測試只是測試,一定要上應用,這個是對自己和公司負責的行為。車已經到了嘉興,俺也吐了兩頁,希望可以擠出瓜哥的玉了。找個信號好的地就發了。嘿嘿。
-唐總原文結束---
唐總說了Host內部的一些注意事項,冬瓜哥借唐總的文章再補充補充,介紹一下外部設備對IO方面的優化。
外部設備的IO優化篇:
冬瓜哥以Memblaze的PBlaze4 NVMe SSD為例來向大家介紹。Memblaze(憶恆創源)作為國內知名固態存儲提供商,曾經推出過國內第一塊NVMe SSDPblaze4,能夠達到將近800K的IOPS,成果國內快閃記憶體廠商性能的新標杆。
那麼Memblaze到底是怎樣達到如此高的性能的?除了藉助給力的控制器硬體之外,在軟體上的幾個優化手法,也是值得其他廠商參考借鑑的。
手法之1:開啟了WB緩存,並用一定量的板載電容保障突然掉電後的髒數據刷盤。不少廠商的產品都是RAMless設計,也就是沒有板載RAM或者板載RAM非常少,僅用於本地代碼運行而不用於數據緩存。
由於數據直接寫入後端Flash也可以達到相對於機械盤來講較高的性能,所以RAMless多數原因是為了節省成本,將FTL表放在主機端RAM,並在主機端實現磨損均衡及垃圾收集計算。但是RAMless的確不利於性能的發揮,尤其是寫性能,WB的緩存不僅僅對機械盤存儲系統頗有用處(可以說是必須的,否則就沒有傳統機械盤存儲系統),對於Flash介質依然奏效,由於NAND Flash存在寫放大,而高壓力場景下對寫IO抖動非常敏感,所以WB緩存的存在事半功倍。
手法之2:全局FTL映射。PBlaze4 SSD後端可以在全部的Flash die顆粒之間實現物理頁到邏輯頁的映射,這樣做的好處無疑是可以實現更廣泛的全局磨損均衡以及更好的性能。而帶來的挑戰則是FTL表的維護和搜索過程變得複雜,但是得益於其16核心並行的控制器硬體的強大處理能力,使得PBlaze4可以承接這個挑戰。
手法之3:Flash通道精細化QoS。PBlaze4控制器後端有16個Flash通道,每個通道下可以掛接多大8個die(Lun),每個Lun有一個深度為4的硬體隊列。正如上文所述,隊列的存在有利於增加吞吐量,但是會對時延帶來影響,尤其是對於NAND Flash這種不怕讀怕寫怕擦的特殊介質,這些不同的IO如果混在雜一起不加以控制的話,會導致嚴重抖動和不可預測。
比如,擦除操作需要至少堵住隊列5ms,這會嚴重提升隊列後面IO的時延。PBlaze4的固件利用了16核心中的2個核心來專門做IO Scheduler並向Lun隊列中填充IO,每個Scheduler各管一半的後端通道。其IO Scheduler的策略是:
每個隊列中最多2個用戶IO和2個元數據寫IO
隊列中不能同時出現用戶IO寫與塊擦除IO
其次,了解IO Scheduler核心思想的人都清楚,IO寫比IO讀往往更容易完成,尤其是下遊IO路徑上有WB緩存的場景下,這樣的話隨著寫IO密集應用發送更多的寫IO入隊,讀IO可能會被餓死導致應用IO超時。PBlaze4的Scheduler採用讀優先策略,但也不絕對,否則會影響寫性能,其內部採用特定算法,在一定場合下會優先,且適當照顧到寫和擦除。
另外,由於PBalze4在Flash顆粒間做了Raid,IO Scheduler還要保證儘量整條寫,也就是針對多個Die的條帶寫IO儘量並行下發,從而更快的釋放內部的XOR Buffer。
手法之4:全流水線負反饋控制。為了進一步保證平穩的IO時延,PBalze4內部採取了全流水線負反饋控制技術。寫時延抖動的根因是由於內部的GC垃圾回收過程,也就是塊擦除IO,每個擦除動作需要5~10ms結束,嚴重影響IO時延。負反饋技術根據當前IO時延作為輸入,反饋到計算引擎,調節GC的頻率,從而動態維持寫時延的恆定。
可以看到採用了該技術之後,IO寫時延非常平穩。
最後,是磚是玉都不重要,都是帶引號的。期待唐老總接招。
不想錯過冬瓜哥的後續精彩文章?長按或掃描下面二維碼關注ssdfans就可以了!
經冬瓜哥授權,轉載自大話存儲公眾號:
公司招聘:
Memblaze華東區高薪招聘,銷售經理,FAE 上海/杭州
聯想SSD專家招聘,FW,QA,NAND特性工程師,北京/武漢
上海飛斯招聘: 存儲開發工程師,RAID、USB、SATA、AHCI、NVME、FTL、文件系統的開發及調試
深圳大普微電子招聘,SSD晶片設計,固件開發,機器學習相關人才!
ssdfans幫你內推
ssdfans幫你賺推薦費
歡迎轉載,請保留二維碼!