預分配——fallocate的前世今生


       最近比較懶,還是加班寫點東西吧,不然過段時間又把這些整理的東西弄丟了。

       寫什么呢?寫一些跟工作相關的吧!因為筆者從事多媒體錄像相關的開發工作,因此常常涉及到優化寫卡策略、提升寫卡性能相關的方面的事情。此話怎講呢?如行車記錄儀類的錄像產品,錄像可能持續多日,越往后寫卡速度會越來越慢,直觀感受是取出視頻文件進行回放時,時間約往后的視頻文件卡頓越來越嚴重。

  怎樣解決呢?一種方案從硬件解決,換一張好卡!但是這不能一勞永逸解決問題,因為錄着錄着寫卡速度又掉下來了。另外一種方案從軟件層面解決,就是卡速變慢了后,將卡格式化,但是這種方案對於用戶來講不太友好(有些用戶可能不知道這個功能,或者文件刪除前備份不方便)。還有一種方案,也是從軟件層面解決問題,就是優化寫卡策略。優化寫卡策略,有一些可行的方案,例如文件預分配、待寫數據進行緩沖寫、編碼與封裝解耦,直寫(DirectIO)。下面內容介紹預分配的內容。

1. fallocate介紹

  linux man手冊說明:

  

  fallocate即預分配,英文為preallocate。什么意思呢?還往文件中沒寫數據,但是已經給文件分配了足額的物理空間來存儲數據。創建了文件,再調用這個接口預分配了一定量的空間后,后續就可以往這個文件中寫數據了。

  另外一點需要注意,這個接口需要文件系統的支持。常用TF卡錄像,而卡的文件系統類型一般為fat32,就需要fat32文件系統相關的實現才能使用該功能。

  再有,這是一個不可移植的linux專用系統調用,用於確保文件空間被提前分配,成功執行后,可以確保寫卡速度較快,也能保證不會因為磁盤空間不足而出現寫失敗。

2 .   接口聲明

函數原型

int fallocate(int fd, int mode, off_t offset, off_t len);

fd

文件句柄

mode

創建模式

offset

偏移

len

文件大小

  其中,在創建了文件后和寫數據前,需要調用該接口進行預分配,第二個參數mode一般設置為1,第三個參數設置為0,第四個參數填上期望預分配值。

3. 應用場景及目標

  應用場景:持續寫卡場景,例如行車記錄儀、運動相機。

  目標:減少磁盤碎片化,提高寫卡速度。

  其他說明:錄像設備的瓶頸常常是寫卡,因為要隨時將視頻文件記錄下來。並且,對持續寫卡速度要求較高,因為錄像設備工作周期可能是以day為單位,不僅要求錄像剛啟動時寫卡正常,而且要求工作了幾天寫卡速度也不能掉太多。至於每秒鍾寫入的數據量,視編碼器輸出碼率和幾路錄像而定,對於單路1080p錄制,視頻碼率設置為10mbps,那么卡速至少要保證2MB/s,這里面還不包括寫log以及錄像中拍照所用的。

  雖然目前時間節點上(2019年末),市面上卡都是C10(10MB/s)及其以上,但是如果寫策略不合理或卡中太多零碎文件,寫速度可能很低。很常見的一個例子,拷貝一個視頻文件到T卡的速度,要遠遠大於拷貝同樣大小的源文件包。另一個例子是,一個剛格式化的T卡與一個內部已經存在了很多文件的T卡(卡品牌、容量、速度等參數都一樣),拷貝同樣大小的文件,剛格式化的那張卡速度更快。

4. 實現原理

  TF卡(TransCard)和SSD(SolidStateDisk)作為常見的存儲設備,內部組成非常類似,都主要由controler和nand flash組成。對於任何存儲設備,我們都最關心三個參數:容量、讀/寫速度、壽命。

  “容量”這個參數勿用介紹,“讀速度”也不介紹,下面主要說下“壽命”和“寫速度”這兩個參數。介紹這兩個參數后,再來介紹預分配。

4.1  壽命相關:

  壽命主要由存儲介質決定,即nand flash這種介質的可擦寫次數,nand flash介質類型的發展經歷了slc、mlc、tlc、qlc(目前市面上還較少)幾個階段,單位面積的容量也越來越大,因為介質類型反映了存儲密度。小小的TF卡,就目前2019年末的這個時間節點上,市面上已經出現了512GB容量的TF卡,存儲多個圖書館書籍的文字信息應該毫無壓力!但是,凡事有利有弊,隨着容量的提升,TF內部的最小存儲單元的可擦寫次數也越來越少。

  SLC(SingleLevelCell)出現最早,可擦寫次數10多萬次;后來出現的MLC(MultiLevelCell)可擦寫次數3000-10000次左右,目前主流的TLC的可擦寫次數在500-1000次左右。在某東上隨便查看了lexar的某款500GB 容量的SSD,其參數如下:

  從中看到閃存類型為TLC,還有TBW=250T這個參數,這個是什么以及怎么得來的呢?

  TBW,即TeraBytesWritten,以TB為單位的寫入的數據量。這個值這樣算:總容量*可寫次數,即500GB*500 = 250TB。其中的500代表平均可寫次數為500,是根據閃存類型TLC來估算的。一般企業級的用的sdd,價格較民用的高不少,例如編譯/數據庫服務器,相同容量的TBW值通常是以PBW(=1024TBW)為單位的,不太追求讀寫速度,但非常看重壽命和可靠性,畢竟數據是無價的。

4.2  速度相關:

  寫速度是個比較玄乎的東西,由許多因素綜合導致,例如,閃存類型、主控算法(固件磨損平衡算法)、文件系統寫策略、卡的碎片化程度、卡的文件系統類型和block大小、內部是否帶Cache以及其大小,等等諸多因素。

  但是,針對確定下來的一張卡,我們需要找到一些方法,來提高寫卡速度。其中一種方法就是預分配——fallocate。

  接下來先介紹文件存儲相關的內容后,再來介紹這個預分配接口的作用。

  對於fat32的文件系統,存儲設備中的某文件,其內容主要包括兩部分:一部分是屬性信息metadata(創建/修改時間、文件名稱、文件大小等),另一部分是真正的數據內容。常用的fdatasync操作只會強制將真正的數據內容刷新到存儲設備中,而fsync會將兩部分內容都刷新到設備中。對於真正的數據內容那部分,有一個鏈表來管理各個塊內容所在的SectorId,即以sector鏈表的形式來完整表述數據內容。因此,某文件的存儲物理地址可能是某連續sector區所在的一整片區域,也可能分布於多個不連續的物理區域。

  存儲設備的碎片化與內存碎片化非常類似,即某文件希望盡可能利用連續的物理存儲空間來存儲數據,但是由於卡已處於高度碎片化狀態,當真正寫入完這個文件時,這個文件在物理空間上是“支離破碎”的。即使是一個剛剛格式化的卡,當兩個線程同時分別寫兩個不同文件時,在物理空間上(內部連續的物理block或sector),這兩個文件可能處於交織狀態(交錯),英文為interleave。做過音頻開發的同事也可以回想一下alsa-lib在打開設備進行參數配置時,針對雙聲道pcm數據采集,有interleave和non-interleave的配置,這個選擇決定了左右聲道pcm數據在一個period內如何排列,類似對比,卡中存儲的多個文件,對於物理block就是這個意思。

  設想一種寫文件場景,使用正常fopen-fwrite-fclose的操作流程,只寫一路,當每次將kernel cache中的數據刷到卡中前,需要現場去找(類似於寫磁盤時的尋道)哪個物理sector是available的,當發現某個block中的某個sector是可用的,但是其他sector是其他文件占用的,那么接下來的策略就是copy-modify-write,即出現了“寫放大”(WriteAmplification)。

  為什么出現這個狀況,需要了解閃存的基本組成:頁page(也稱sector,大小4KB) -> 塊block(通常64或128個page組成一個block) -> 面plane(多個block組成) –> die(plane就是一個die) -> 閃存片(多個die組成) –> SSD或TF(多顆閃存片組成)。

  下面描述下寫放大過程:先把整個block中的數據完全拷貝到ddr,再將某個sector中的數據修改為期望寫入的數據,擦掉ssd中這個block的內容,然后再整體將ddr中的已修改好的數據寫入到ssd中這個block位置。為什么要這樣做?因為寫入是按block為最基本單位進行的。所以寫入一筆數據,涉及了多次基本操作,不僅減慢了寫速度,而且減少了壽命。然而,當進行了預分配后,提前為某文件划分了“勢力范圍”,標定某些位置已經被占用,可以減少后續的寫放大和尋找可用空間的過程。

4.3  預分配原理:

  介紹了文件存儲結構的相關內容后,對於預分配的功能我們就有了大致的猜測!fallocate這個接口,其要實現的目的,就是在數據內容還未寫入到設備前,提前為文件分配好若干大小的空間,並且使這個空間盡可能是物理連續的,這樣可以減少后續寫放大的出現頻率,以及不需在寫入過程中尋找可用空間,更不會出現寫數據時磁盤空間不足的問題!

5. 其他問題

  使用預分配一個最大的問題是——磁盤空間利用率不高!這個如何說起?文件剛創建還未寫入數據,我們就搶先為文件設置了文件的大小並占用了固定大小的物理空間,但通常可能未寫入那么大size的數據量就fclose了這個文件,那么這個文件內未寫入的空間就不能被其他文件利用了。一個文件預分配了100MB,即使只寫入1MB就關閉,那么就有99MB的空間浪費。但是,使用預分配對於行車記錄儀類產品是個較優的選擇,因為文件切換是定時切換的,如果編碼器輸出碼率是相對穩定的,就可以預估最終文件大小,預分配的大小再留些余量就可以了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM