作者簡介
小輝,一線碼農(nóng),有多年豐富嵌入式操作系統(tǒng)開發(fā)工作經(jīng)驗。先后在南大富士通,某手機大廠和初創(chuàng)小公司任軟件工程師,系統(tǒng)架構(gòu)師等職務(wù)。對嵌入式系統(tǒng)開發(fā)和os性能優(yōu)化工作很熟悉。在此特別鳴謝!
引子
自己做單機存儲性能優(yōu)化工作已經(jīng)一年多了,平時組內(nèi)做的優(yōu)化點需要系統(tǒng)總結(jié)一下了。
怎么能夠找到手機存儲性能優(yōu)化方面的技術(shù)特性,怎么去凸顯手機存儲里面碰到的獨特性能優(yōu)化問題,有了這些需求,所以我需要寫一點東西了。
因為工作繁忙,只好寫成了類似bbs和筆記的風(fēng)格,不過雖然這樣,我保證下面文字是我對手機存儲性能架構(gòu)方面的原創(chuàng)心得,網(wǎng)上根本搜不到下面這樣的文字。
手機安卓系統(tǒng)IO特性
業(yè)務(wù)方面特性
手機存儲對應(yīng)的都是單機存儲架構(gòu)。出存儲性能問題時,往往直觀的表現(xiàn)是桌面運行卡頓,
需要分析用戶上傳的bugreport,然后自己根據(jù)用戶場景做問題復(fù)現(xiàn),然后通過分析內(nèi)核ftrace log, 還有借助一些性能排查工具去解決該性能問題。
技術(shù)方面特性
1: buffer IO很多,異步IO,direct IO很少
手機中異步IO,direct IO操作應(yīng)該很少,基本上都是buffer IO(經(jīng)過page cache的IO),所以出存儲性能問題時,尋找根本原因時,往往是內(nèi)存原因和IO原因交織混雜在一塊,表現(xiàn)出來的原因,并不是孤立的IO模塊的原因。
內(nèi)存原因有內(nèi)存回收,內(nèi)存slow path分配,IO原因有具體的文件系統(tǒng),還有塊設(shè)備層IO調(diào)度器。
2: sqlite數(shù)據(jù)庫引發(fā)的IO操作很多
這個是手機系統(tǒng)的一個很重要的IO特色,詳見三星公司出的那篇經(jīng)典Android IO特性分析論文。
Android 手機里面大部分寫都是數(shù)據(jù)庫sqlite的單筆小量數(shù)據(jù)的頻繁同步隨機寫(就是write+fsync),而不是服務(wù)器場景中出現(xiàn)的文件寫。
3:手機里面大部分都是中低速存儲芯片,比如emmc, ufs。所以內(nèi)核層的over head不高,需要利用到內(nèi)核的文件系統(tǒng),還有IO調(diào)度器
這個涉及到內(nèi)核存儲架構(gòu)問題了。
1)現(xiàn)有的存儲系統(tǒng),在分布式和大數(shù)據(jù)應(yīng)用場景下,通常會用些高速存儲芯片(比如nvme接口的),內(nèi)核現(xiàn)有的存儲架構(gòu)不能有效的發(fā)揮作用。
具體表現(xiàn)在每一筆的IO下發(fā),在內(nèi)核存儲棧產(chǎn)生的over head太重了,并且還不能充分地利用存儲芯片的IO帶寬。
尤其是塊設(shè)備層那些傳統(tǒng)的single queue設(shè)計,IO 請求排序和合并,cfq調(diào)度器,傳統(tǒng)文件系統(tǒng)自身局限性等這些內(nèi)核的設(shè)計思想,都不符合高速存儲的需求。
所以現(xiàn)有的分布式和大數(shù)據(jù)存儲場景,都是會bypass 內(nèi)核,直接做成用戶態(tài)driver去直接讀寫存儲芯片的,比如現(xiàn)在的dpdk, spdk架構(gòu)。
所以現(xiàn)在內(nèi)核也被迫的調(diào)整存儲架構(gòu),io_urging, 塊設(shè)備層的blk-mq多隊列設(shè)計,bfq調(diào)度器等這些存儲架構(gòu)的調(diào)整都是為了跟上當(dāng)前硬件上,存儲芯片性能不斷暴漲的節(jié)奏。
2)但是手機場景是比較特殊的,因為用的還是emmc,ufs這種存儲芯片速度不是特別快的場景,再加上每天的實際存儲數(shù)據(jù)寫入耗時占每天總時長的比例是比較小的(sandisk有存儲芯片打點數(shù)據(jù)分析的),再加上上面的2點IO特性,所以手機場景下,還是會用到內(nèi)核傳統(tǒng)的文件系統(tǒng),塊設(shè)備層設(shè)計思想,會用到這些傳統(tǒng)的內(nèi)核存儲架構(gòu)。
4:會頻繁異常掉電,所以對文件系統(tǒng)穩(wěn)定性要求高
服務(wù)器場景會有ups電源,可能很少會有系統(tǒng)頻繁掉電的場景出現(xiàn)。
但是手機場景,據(jù)我們分析,就算用戶選擇的是正常關(guān)機流程,也會很多時候出現(xiàn)因為文件系統(tǒng)卸載超時導(dǎo)致的實際上走的也是類似于這種異常掉電流程(就是雖然不是異常掉電,但是走的流程,還有從對存儲數(shù)據(jù)穩(wěn)定性影響方面評估,跟異常掉電場景區(qū)別不大)。
所以就更不用提很多時候,用戶關(guān)不了機時(系統(tǒng)按鍵無響應(yīng)時),往往采取的強制掉電關(guān)機或者掉電重啟。
5:會有前后臺任務(wù)管理方面的工作需求
因為安卓手機通常后臺跑的做IO工作的進程數(shù)量是很多的,同時用戶在前臺操作手機時,前臺的任務(wù)不希望被后臺任務(wù)所干擾。
隨著內(nèi)存越來越大,還有安卓本來就是多任務(wù)系統(tǒng),所以安卓后臺跑的進程數(shù)量是比較多的。但是用戶在前臺操作app或者圖形界面時,是不希望受到后臺進程的干擾影響的。
6:手機會出現(xiàn)存儲碎片化厲害的場景,這樣對IO性能會影響比較大。
手機里面大部分都是存儲的小文件,但是手機存儲容量往往由于成本和具體應(yīng)用原因,不會容量像大數(shù)據(jù)或者分布式的存儲容量那么大。
而且隨著手機應(yīng)用場景越來越豐富,比如視頻,聊天,當(dāng)做電腦一樣在應(yīng)用手機,所以手機本來存儲容量就不大,再加上使用時間長和強度高后,存儲碎片化現(xiàn)象肯定越來越嚴(yán)重(具體表現(xiàn)在文件系統(tǒng)碎片化)。
這樣對IO性能會有大的影響的。
7:會有ext4文件系統(tǒng)的自身局限性帶來的一些問題
設(shè)計ext4的時候,當(dāng)時都是機械硬盤為主,內(nèi)存資源不充足的時代,現(xiàn)在的時代是以flash為主,手機已經(jīng)稍微邁入了大內(nèi)存時代。
ext4的局限性:
1)原地更新數(shù)據(jù)特性,會加重存儲芯片里面的IO寫放大問題。
2)ext4+jbd2的journal架構(gòu)設(shè)計。
這個設(shè)計雖然是為了實現(xiàn)文件系統(tǒng)日志功能,它采用了類似c語言式的簡單直觀的設(shè)計思想(ext4社區(qū)ted有相關(guān)郵件說明),同時采取physical logging,也是為了追求復(fù)用內(nèi)存,節(jié)省內(nèi)存。
但是這種類c語言的設(shè)計思想,雖然當(dāng)初設(shè)計時,可以做到簡單高效。但是不好的地方在于:
1> 隨著多核處理器架構(gòu)的普及,這種設(shè)計思想帶來的性能瓶頸問題越來越厲害。
2> 這種設(shè)計思想容易造成內(nèi)核的IO優(yōu)先級倒置問題(具體見下面的fsync慢原因分析)。
3)是針對機械硬盤進行設(shè)計的,沒有突出flash - aware.
綜合這些ext4自身局限性,造成了對手機IO性能的不良影響,所以 f2fs出現(xiàn)了。
8:會結(jié)合emmc/ufs存儲芯片里面的ftl固件實現(xiàn)思想去定位性能問題
1)因為解決的是單機存儲性能問題,所以想要精確評估性能優(yōu)化方案會對手機帶來多大的性能提升,需要對存儲芯片里面的固件工作原理,工作思想有所了解。
2)手機換成了f2fs文件系統(tǒng)后,因為f2fs文件系統(tǒng)的設(shè)計初衷就是flash - aware,所以更需要了解存儲芯片里面的固件后,才能準(zhǔn)確把握和ext4相比,f2fs帶來的性能優(yōu)化效果。
手機存在的存儲性能問題
針對上面羅列的Android系統(tǒng)的一些IO特性,手機存在的存儲性能問題如下
1:針對特性1,2,3和5,會有ext4的fsync問題
原因在于下面幾點:
1)Android系統(tǒng)里面sqlite寫數(shù)據(jù)時,sqlite自身的日志架構(gòu)設(shè)計,會導(dǎo)致頻繁下發(fā)fsync。這樣后臺fsync下發(fā)多了,前臺或者system server里面下發(fā)fsync就會受到影響(fsync耗時會增加很多),
2)同時手機安卓系統(tǒng)還有一些原生特性,就是jbd2工作在order模式下的, 同時又開啟了ext4 延遲分配功能,這樣也會加重fsync耗時。
1> order模式加重耗時原因:
order模式下,jbd2不得不去在commit thread里面多了個等待臟iNode的數(shù)據(jù)全部刷到盤上的工作。所以jbd2 commit thread耗時增加,會帶來fsync的耗時也會增加不少,
因為fsync最后一步是要等待自身的事務(wù)被commit thread處理完成。
2> 內(nèi)核存儲IO優(yōu)先級倒置加重耗時原因:
CFQ I/O調(diào)度器在調(diào)度io請求時,會優(yōu)先去調(diào)度同步的io請求,這樣會導(dǎo)致異步io請求的處理時間變長。應(yīng)用調(diào)用fsync的時候,fsync自身下發(fā)的IO請求都是同步的,這是從存儲設(shè)計角度,為了追求提升fsync性能。
但是系統(tǒng)如果剛好正在進行內(nèi)存臟頁回寫,這個時候fsync需要等待臟頁回寫對應(yīng)的異步io請求完成后,fsync的工作才能算做完。這樣就會導(dǎo)致fsync耗時。
3> 延遲分配加重耗時原因:
延遲分配會加重單次fsync的負(fù)擔(dān),因為系統(tǒng)flush thread是每隔30秒觸發(fā)的(Android系統(tǒng)里面),
然后flush thread 在前,fsync在后的話,容易fsync卡在order模式中的等待file data flush到disk中 這個地方,等很久
(因為之前的flush thread里面已經(jīng)為臟的iNode分配了很多物理blocks,并且把這些臟iNode(每隔30s去觸發(fā)flush thread的話,是會產(chǎn)生很多臟iNode的)注冊到了jbd2的transaction里面,
jbd2里面多了個額外等待這些臟iNode里面臟數(shù)據(jù)被刷到磁盤上的操作)。
flush thread 在后,fsync在前的話,沒有這個問題。
3)ext4的實時discard機制也會造成fsync慢的問題。
這樣在手機Android系統(tǒng)里面,由于上面種種原因,造成fsync響應(yīng)慢,然后就會表現(xiàn)出手機前臺操作卡頓或者卡死直接安卓層重啟的現(xiàn)象。
2:針對特性6,會有文件系統(tǒng)碎片化導(dǎo)致存儲IO性能下降的問題
手機data分區(qū)碎片化厲害后,會導(dǎo)致:
1)手機的寫性能(順序?qū)懀S機寫性能,direct寫)會下降的(之前我詳細(xì)分析過原因的,并挖掘過性能下降的具體場景)。
2)手機的sqlite數(shù)據(jù)庫IO性能也會下降很多的(之前跟存儲芯片廠商共同定位過該下降的原因)。
3:針對特性1,3和5,會有前后臺IO管理的問題
1)特殊場景出現(xiàn)的問題:后臺U盤拷貝時,前臺安卓桌面操作卡頓問題出現(xiàn)。
原因:
i:U盤拷貝數(shù)據(jù)量大時,導(dǎo)致內(nèi)存里面臟頁變多,然后可用free內(nèi)存變少。
ii:然后前臺手機操作時,會alloca_pages,這個時候會觸發(fā)內(nèi)存回收,去回收臟頁,這樣io又變多,阻塞了申請內(nèi)存的前臺用戶進程。
2)通用場景出現(xiàn)的問題:后臺做的IO任務(wù)異常活躍,干擾了前臺任務(wù)的運行,需要前后臺任務(wù)進行協(xié)作。
原因:
i:? Android的IO調(diào)度器為cfq,并未區(qū)分前后臺。這樣后臺app或者進程正在進行IO工作時,會搶占前臺app的IO帶寬和內(nèi)存資源。
現(xiàn)在的核心優(yōu)化需求是怎么保證用戶在前臺操作app,或者圖形界面時,一直都是流暢的,即使后臺跑再多的任務(wù),對前臺也沒有影響。
4:針對特性4,會有文件系統(tǒng)穩(wěn)定性問題
存儲性能優(yōu)化會對文件系統(tǒng)做一些深入修改,以前的測試強度還不夠。
對文件系統(tǒng)深入修改后,以前的測試case還不能深入進行文件系統(tǒng)測試。
5:針對特性7,存在的問題上面已經(jīng)做分析了
6:針對特性8,會存在需要存儲芯片廠商的支援和配合問題
ftl固件是存儲芯片廠商的專利,給我們暴露的存儲芯片使用接口太少。他們雖然很配合我們的性能優(yōu)化工作,但是通常涉及到他們芯片固件實現(xiàn)的一些敏感問題,會回避我們。
需要我們自己去理解ftl的一些通用設(shè)計思想,另外聯(lián)合采購人員,一起去跟存儲芯片廠商進行性能問題的溝通和解決。
具體問題場景如下:
1)部署無感垃圾回收優(yōu)化方案時,需要準(zhǔn)確的評估該優(yōu)化會帶來哪些IO性能提升。
2)上面的碎片整理對Android sqlite數(shù)據(jù)庫IO性能的提升的根本原因調(diào)研。
現(xiàn)有的性能優(yōu)化措施
針對上面羅列的手機存在的若干存儲性能問題,具體優(yōu)化工作如下:
問題1的優(yōu)化:
1)無感垃圾回收優(yōu)化,是針對上面的原因3
2)ext4 fsync專項優(yōu)化,是針對上面的原因2
3)sqlite io優(yōu)化,是針對上面的原因1
上面是結(jié)合手機業(yè)務(wù)場景,做的簡單有效的優(yōu)化方案,最根本最徹底的優(yōu)化方案是下面的:
4)社區(qū)的fast commit方案 (正在開發(fā)中,有這一個方案就可以徹底解決問題,不需要上面3個了)。
問題2的優(yōu)化:
就是目前的ext4碎片整理方案。具體有兩個優(yōu)化措施:
1)compact整理,解決的是上面說的寫性能下降的問題。
2)單文件碎片整理,解決的是上面說的sqlite數(shù)據(jù)IO性能下降的問題。
問題3的優(yōu)化:
1)針對上面的U盤拷貝導(dǎo)致的性能問題,社區(qū)有相關(guān)優(yōu)化方案,具體是對內(nèi)存回收方面做點優(yōu)化。
2)針對這個前后臺的性能問題,結(jié)合手機業(yè)務(wù)場景方面的優(yōu)化有IO限速方案。
3)徹底的最根本的優(yōu)化是前后臺分組,即運用cgroup v2分組方案,前臺給予比較多的IO和內(nèi)存資源請求,后臺給予少點,目前我有所調(diào)研,做過一些優(yōu)化方案設(shè)計。
(cgroup v2對于buffer io會有些優(yōu)先級倒置問題,部分原因跟那個mmap_sem鎖整個進程地址空間的缺陷是相關(guān)的,目前盡量在高版本內(nèi)核上(大于4.14的)做cgroup v2方案)
問題4的優(yōu)化:
就是需要導(dǎo)入目前的xfstest,以便對穩(wěn)定性測試方面加大測試強度。
問題5的優(yōu)化:
針對上面說的ext4文件系統(tǒng)的局限性,需要用f2fs來代替ext4了。
大內(nèi)存時代,讀性能沒有寫性能那么需要得到工程師的迫切優(yōu)化,因為內(nèi)存大,很多文件第一次讀完后,就緩存在內(nèi)存里面了。
往往是寫性能會導(dǎo)致出現(xiàn)存儲IO性能問題。
所以f2fs針對手機寫場景,做的優(yōu)化如下:
1)對數(shù)據(jù)庫寫專門做了優(yōu)化(sqlite原子寫).
2)提出了將隨機寫轉(zhuǎn)換為順序?qū)?,還有copy on write思想.
3)針對手機存儲芯片的一些物理特性,做了冷熱數(shù)據(jù)分離功能.
這樣優(yōu)化措施,可以減少了flash的寫放大問題(寫放大,會導(dǎo)致用戶長期使用手機后,會出現(xiàn)flash壞塊增多,會導(dǎo)致存儲芯片自身固件做GC時間增多,這樣IO性能就會下降了),
可以提升Android的隨機寫性能,同時又是logical logging,所以沒有jbd2那個導(dǎo)致的fsync問題出現(xiàn)。
所有的這些f2fs優(yōu)化,都是針對手機寫場景做的針對性優(yōu)化,ext4是沒有的。
所以為了突破現(xiàn)有的ext4架構(gòu)上導(dǎo)致的存儲性能問題缺陷,所以f2fs在手機場景應(yīng)該取代ext4。
上f2fs后,有兩個性能優(yōu)化點需要關(guān)注:
1)f2fs的gc效率(重點是后臺的)
2)f2fs的冷熱數(shù)據(jù)分離效果。
這兩點的優(yōu)化好壞能關(guān)系到f2fs的dirty segments數(shù)目降低多少。只有dirty segments數(shù)目降低了,free segments數(shù)目增加的多了,系統(tǒng)的IO性能才能好起來。
問題6的優(yōu)化:
1)自己可以看這本書:深入淺出ssd,仔細(xì)理解該書后,會對ftl的設(shè)計思想有所理解。
2)已經(jīng)解決了上面的問題場景2,問題場景1正在解決中。
2)已經(jīng)進行了幾次存儲芯片原廠舉辦的關(guān)于存儲芯片內(nèi)部軟硬件實現(xiàn)的培訓(xùn)會議,通過這些會議,已經(jīng)對ftl固件,還有存儲芯片的一些物理特性有所理解。
PS:
優(yōu)化點上面已經(jīng)羅列出來了,具體的各個優(yōu)化點實現(xiàn)內(nèi)容,由于涉及保密方面原因,不便在文章公開了。感興趣可與作者溝通交流
電子發(fā)燒友App












評論