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