I/O優(yōu)化

I/O基本知識


整個I/O操作由應用程序驹饺、文件系統(tǒng)和磁盤共同完成懦砂,應用程序?qū)/O命令發(fā)送到文件系統(tǒng)窿给,文件系統(tǒng)在合適的時機把I/O操作發(fā)送給磁盤拳缠。整個流程的瓶頸在于磁盤I/O覆获,但有時文件系統(tǒng)為了降低磁盤對應用程序的影響马澈,會采用各種方式進行優(yōu)化,因為文件系統(tǒng)的性能變得十分重要弄息。

1痊班、文件系統(tǒng)

文件系統(tǒng),簡單來說既是存儲和組織數(shù)據(jù)的方式摹量。對于Android來說普遍采用的文件系統(tǒng)是Linux的常用的ext4文件系統(tǒng)涤伐,華為在EMUI5.0以后就使用F2FS取代ext4馒胆,谷歌也在最新的旗艦手機Pixel3使用了F2FS文件系統(tǒng)。F2FS文件系統(tǒng)在小文件隨機讀寫方面比ext4更快凝果,不足之處在于可靠性方面出現(xiàn)過一點問題祝迂,隨著谷歌和華為的投入和使用,未來F2FS將成為Android的主流文件系統(tǒng)器净。
應用程序調(diào)用read()方法型雳,系統(tǒng)會通過中斷從用戶空間進入內(nèi)核處理流程,然后經(jīng)過VFS(Virtual File System山害,虛擬文件系統(tǒng))纠俭、具體文件系統(tǒng)、頁緩存Page Cache浪慌。下面是Linux一個通用I/O架構模型


I/O架構模型
  • 虛擬文件系統(tǒng)(VFS)冤荆。它主要用于實現(xiàn)屏蔽具體的文件系統(tǒng),為應用程序的操作提供一個統(tǒng)一的接口权纤。
  • 文件系統(tǒng)(File System)钓简。文件系統(tǒng)需要考慮具體文件元數(shù)據(jù)如何組織、目錄和索引結構如何設計汹想,怎么分配和清理數(shù)據(jù)涌庭。
  • 頁緩存(Page Cache)。Page Cache就像我們經(jīng)常使用的數(shù)據(jù)緩存欧宜,是文件系統(tǒng)對數(shù)據(jù)的緩存,目的是提升內(nèi)存命中率拴魄。通過/proc/meminfo文件可以查看緩存的內(nèi)存占用情況冗茸,當手機內(nèi)存不足時,系統(tǒng)會回收他們的內(nèi)存匹中,這樣整體I/O的性能就會有所降低夏漱。

2、磁盤

磁盤指的就是系統(tǒng)的存儲設備顶捷。當應用程序要read()的數(shù)據(jù)沒有在頁緩存中挂绰,這時候就需要真正想磁盤發(fā)起I/O請求,這個過程要先經(jīng)過內(nèi)核的通用模塊層服赎、I/O調(diào)度層葵蒂、設備驅(qū)動層,最后才會交給具體的硬件設備處理重虑。


  • 通用塊層践付。系統(tǒng)中能夠隨機訪問固定大小數(shù)據(jù)塊(block)的設備成為設備,CD缺厉、磁盤和SSD這些都輸設備永高。通用塊層主要作用是接收上層發(fā)出的磁盤請求隧土,并最終發(fā)出I/O,他的作用類似VFS命爬,提供通用接口曹傀,屏蔽下層實現(xiàn)。
  • I/O調(diào)度層饲宛。為了降低真正的磁盤I/O皆愉,我們不能接收到I/O操作后就立即執(zhí)行,而是交由I/O調(diào)度層落萎,根據(jù)不同的算法亥啦,對請求進行合并和排序。
  • 塊設備驅(qū)動層练链。 塊設備驅(qū)動層根據(jù)具體的物理設備翔脱,選擇對應的驅(qū)動程序操控硬件設備完成最終的I/O請求。

Android I/O

閃存是手機常用的存儲設備媒鼓,Android手機前幾年通常使用eMMC標準届吁,近年來通常會使用性能更好的UFS2.0/2.1標準。

1绿鸣、文件為什么會損壞:

一個文件的格式或者內(nèi)容疚沐,如果沒有按照應用程序?qū)懭霑r的結果都屬于文件損壞。

  • 應用程序潮模。大部分I/O方法都是非原子操作亮蛔,文件的跨進程或多線程寫入、使用一個已經(jīng)關閉的文件描述符fd來操作文件擎厢,它們都有可能導致文件內(nèi)容修改和刪除究流。
  • 文件系統(tǒng)。文件系統(tǒng)把數(shù)據(jù)寫入到頁緩存动遭,在合適的時機寫入到磁盤芬探,內(nèi)核崩潰和斷電就有可能導致寫入到磁盤異常和沒有寫入。
  • 磁盤厘惦。磁盤屬于電子設備偷仿,內(nèi)容在傳輸過程中存在錯誤的可能,同時閃存的壽命也可能導致文件錯誤宵蕉。

2酝静、I/O為什么會突然變慢:

  • 內(nèi)存不足,當手機內(nèi)存不足時羡玛,系統(tǒng)會回收Page Cache和Buffer Cache的內(nèi)存形入,大部分的寫操作會直接落盤,導致性能低下缝左。
  • 寫入放大亿遂,閃存重復寫入需要先擦除操作浓若,這個擦除操作是以block塊為基本單元的,一個page的寫入操作會引起整個塊數(shù)據(jù)遷移蛇数。低端機或者使用很久的設備挪钓,由于磁盤碎片多、剩余空間少耳舅,非常容易出現(xiàn)寫入放大的現(xiàn)象碌上。
  • 低端機的CPU和閃存性能相對較差,在高負載的情況下容易出現(xiàn)瓶頸浦徊。
    系統(tǒng)為了緩解磁盤碎片問題馏予,可以引入fstrim/TRIM機制,在鎖屏盔性、充電等一些時機會觸發(fā)磁盤碎片整理霞丧。

I/O的性能評估

1、I/O性能指標

最核心的指標為吞吐量和IOPS冕香。吞吐量是指單位時間的數(shù)據(jù)讀取或?qū)懭敕逯涤汲ⅲ琁OPS指的是每秒可以讀寫的次數(shù)。

2悉尾、I/O測量

  • 使用proc
  • 使用strace突那,可以跟蹤I/O相關的系統(tǒng)調(diào)用次數(shù)和耗時
  • 使用vmstat

I/O的三種方式

1、標準I/O

應用程序平時用到的read/write操作都屬于標準I/O构眯,也就是緩存I/O(Buffered I/O)愕难。其特點為:

  • 對于讀操作來說,當應用程序讀取到某塊數(shù)據(jù)時惫霸,如果這塊數(shù)據(jù)已經(jīng)存放在頁緩存中务漩,那么這塊數(shù)據(jù)之間返回,不需要實際的物理操作它褪。
  • 對于寫操作來書,應用程序也會將數(shù)據(jù)寫到頁緩存中去翘悉,數(shù)據(jù)是否被立即寫到磁盤上取決于應用程序所采用的寫操作機制茫打。默認系統(tǒng)采用延遲寫機制,應用程序只需寫入頁緩存妖混,系統(tǒng)負責定期寫入到磁盤老赤。
    Page Cache中被修改的內(nèi)存稱為“臟頁”,內(nèi)核通過flush線程定期將數(shù)據(jù)寫入磁盤制市,具體寫入的條件我們可以通過/proc/sys/vm文件或sysctl -a | grep vm命令得到抬旺。如果某些數(shù)據(jù)非常重要,不允許出現(xiàn)丟失的風險祥楣,這個時候可以采用同步寫機制开财,在應用程序中使用sync汉柒、fsync、msync等系統(tǒng)調(diào)用時责鳍,內(nèi)核都會將相應的數(shù)據(jù)寫回到磁盤碾褂。


2、直接I/O


直接I/O訪問文件方式減少了一次數(shù)據(jù)拷貝和一些系統(tǒng)調(diào)用時間历葛,很大程度上降低了CPU的使用率以及內(nèi)存的占用正塌。但是,直接I/O有時候也會對性能產(chǎn)生不良影響:

  • 對于讀操作來說恤溶,讀數(shù)據(jù)操作會造成磁盤同步讀乓诽,導致進程需要較長時間才能執(zhí)行完;
  • 對于寫操作來說咒程,使用直接I/O也需要同步執(zhí)行鸠天,也會導致程序等待。

3孵坚、mmap

它是通過吧文件映射到進程的地址空間粮宛,帶來的好處有:

  • 減少系統(tǒng)調(diào)用。只需一次mmap()系統(tǒng)調(diào)用卖宠,后續(xù)所有調(diào)用像操作內(nèi)存一樣巍杈,而不會出現(xiàn)大量的read/write系統(tǒng)調(diào)用。
  • 減少數(shù)據(jù)拷貝扛伍。普通的read()操作需要經(jīng)過兩次拷貝筷畦,而mmap只需要從磁盤拷貝一次,并且由于做過內(nèi)存映射刺洒,也不需要再拷貝回用戶空間鳖宾。
  • 可靠性高。mmap把數(shù)據(jù)寫入緩存逆航,跟緩存I/O的延遲寫機制是一樣的鼎文,可以依靠內(nèi)核線程定期寫回磁盤。但是在內(nèi)核崩潰或斷電的時候因俐,同樣可能引起內(nèi)容丟失拇惋,也可以使用msync來強制同步寫。



    mmap同樣也存在缺點:

  • 虛擬內(nèi)存增大抹剩。mmap會導致虛擬內(nèi)存增大撑帖,mmap一個大文件,有可能出現(xiàn)虛擬內(nèi)存不足而導致OOM澳眷。
  • 磁盤延遲胡嘿。mmap通過缺頁中斷向磁盤發(fā)起真正的磁盤I/O,所以如果當前的問題在于磁盤I/O的高延遲钳踊,那么用mmap()消除小小的系統(tǒng)調(diào)用開銷是杯水車薪的衷敌。類重排技術勿侯,就是將Dex中類按照啟動順序重新排列,主要為了減少缺頁中斷造成的磁盤I/O延遲逢享。
    mmap比較適合對同一塊區(qū)域頻繁讀寫的情況罐监,用戶日志、數(shù)據(jù)上報都滿足這種場景瞒爬,另外跨進程通訊的時候也是不錯的選擇弓柱。Android跨進程通訊的Binder機制,其內(nèi)部實現(xiàn)就是采用的mmap實現(xiàn)侧但。
    利用mmap矢空,Binder在跨進程通訊只需要一次數(shù)據(jù)拷貝,比傳統(tǒng)的Socket禀横、管道等跨進程通訊方式會少一次數(shù)據(jù)拷貝屁药。


多線程阻塞I/O和NIO

1、多線程阻塞I/O

文件讀寫受到I/O性能瓶頸的影響柏锄,在到達一定速度后整體性能就會受到明顯影響酿箭,過多的線程反而導致應用整體性能明顯下降。

2趾娃、NIO


非阻塞NIO將I/O以事件的方式通知缭嫡,的確可以減少線程切換的開銷。其缺點是導致應用程序?qū)崿F(xiàn)變得更復雜抬闷。其實NIO最大作用不是減少讀取文件的耗時妇蛀,而是最大化提升應用整體的CPU利用率怎茫。在CPU繁忙地時候符喝,我們可以將線程等待磁盤I/O的時間來做部分CPU操作嗤瞎。

I/O跟蹤

1芬首、Java Hook

出于穩(wěn)定性的考慮,采用Java Hook的方案将宪,通過動態(tài)代理的方式苞七,在所有I/O相關方法前后加入插裝代碼器予,統(tǒng)計I/O操作相關信息培遵。這個方法存在下列缺點:

  • 性能極差浙芙。
  • 無法監(jiān)控Native代碼。
  • 兼容性差荤懂。

2、Native Hook

Profilo使用PLT Hook方案塘砸,它的性能比GOT Hook要稍好些节仿,不過GOT Hook的兼容性更好一些。

3掉蔬、監(jiān)控內(nèi)容

線上監(jiān)控

通過Native Hook方案可以采集到所有I/O相關的信息廊宪,對于I/O的線上監(jiān)控矾瘾,我們需要進一步抽象出規(guī)則,明確哪些情況可以定義為不良情況箭启,需要上報到后臺壕翩,進而推動開發(fā)去解決。


1傅寡、主線程I/O

有時候I/O的寫入會突然放大放妈,所以盡量不要在主線程上操作,線上也經(jīng)常發(fā)現(xiàn)一些I/O操作明明數(shù)據(jù)量不大荐操,但是最后還是出現(xiàn)ANR芜抒。如果將主線程的所有I/O都收集起來,數(shù)據(jù)量會非常大托启,所以可以加上“連續(xù)讀寫時間超過100毫秒”這樣的條件宅倒,之所以連續(xù)讀寫,是因為不少情況這是打開了文件句柄屯耸,但不是一次讀寫完的拐迁。

2、讀寫B(tài)uffer過小

文件系統(tǒng)讀寫是以Block為單位的疗绣,對于磁盤是以Page為單位讀寫线召,如果我們的Buffer太小會導致對此無用的系統(tǒng)調(diào)用和內(nèi)存拷貝,導致read/write次數(shù)增多持痰,從而影響性能灶搜。Buffer的大小對文件的讀寫的耗時有非常大的影響,耗時減小主要得益于系統(tǒng)圖調(diào)用于內(nèi)存拷貝的優(yōu)化工窍,Buffer的大小一般推薦使用4KB以上割卖。

3、重復讀

如果頻繁的讀取某個文件患雏,并且這個文件一直沒有被寫入跟新鹏溯,我們可以通過緩存來提升性能,不過未來減少上報量淹仑,通常增加幾個條件:

  • 重復讀取次數(shù)超過3次丙挽,并且讀取的內(nèi)容相同。
  • 讀取期間文件內(nèi)容沒有被更新匀借,也沒有發(fā)生過write

4颜阐、資源泄漏

資源泄漏是指打開資源包括文件、cursor等沒有及時關閉吓肋,從而引起的泄漏凳怨。利用Android 框架中的StrictMode實現(xiàn)監(jiān)控資源泄漏,StrictMode利用CloseGuard.java類在很多系統(tǒng)代碼已經(jīng)預制了埋點,我們可以增加更多的埋點肤舞,據(jù)圖步驟如下:

  • 利用反射紫新,吧CloseGuard中的ENABLED的值為true。
  • 利用動態(tài)代理李剖,把REPORTER替換成我們定義的proxy芒率。

I/O啟動優(yōu)化

  • 對大文件使用mmap或者NIO方式。
  • 安裝包不壓縮篙顺。對啟動過程需要的文件偶芍,指定不壓縮,這樣會加快啟動速度慰安,但會帶來安裝包體積增大的問題腋寨。
  • Buffer復用。重用技巧化焕,如Okio很大程度上減少CPU和內(nèi)存的消耗萄窜。
  • 存儲結構和算法優(yōu)化。從存儲結構和算法優(yōu)化方面減少甚至去除I/O操作撒桨。
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末查刻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凤类,更是在濱河造成了極大的恐慌穗泵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谜疤,死亡現(xiàn)場離奇詭異佃延,居然都是意外死亡,警方通過查閱死者的電腦和手機夷磕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門履肃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坐桩,你說我怎么就攤上這事尺棋。” “怎么了绵跷?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵膘螟,是天一觀的道長。 經(jīng)常有香客問我碾局,道長荆残,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任净当,我火速辦了婚禮内斯,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己嘿期,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布埋合。 她就那樣靜靜地躺著备徐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甚颂。 梳的紋絲不亂的頭發(fā)上蜜猾,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音振诬,去河邊找鬼蹭睡。 笑死,一個胖子當著我的面吹牛赶么,可吹牛的內(nèi)容都是我干的肩豁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辫呻,長吁一口氣:“原來是場噩夢啊……” “哼清钥!你這毒婦竟也來了?” 一聲冷哼從身側響起放闺,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤祟昭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后怖侦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篡悟,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年匾寝,在試婚紗的時候發(fā)現(xiàn)自己被綠了搬葬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡旗吁,死狀恐怖踩萎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情很钓,我是刑警寧澤香府,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站码倦,受9級特大地震影響企孩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜袁稽,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一勿璃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦补疑、人聲如沸歧沪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诊胞。三九已至,卻和暖如春锹杈,著一層夾襖步出監(jiān)牢的瞬間撵孤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工竭望, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邪码,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓咬清,卻偏偏與公主長得像闭专,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子旧烧,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 文件系統(tǒng)優(yōu)化 ** 動態(tài)調(diào)整請求隊列數(shù)來提高效率,默認請求隊列數(shù)為:128, 可配置512 **[root@c37...
    肖金光xjg閱讀 4,784評論 1 8
  • Bitmap decode BitmapFactory.java提供多個decode Bitmap的API喻圃,有de...
    developerChenxi閱讀 3,831評論 0 0
  • feisky云計算、虛擬化與Linux技術筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,815評論 0 5
  • I/O 操作是編程離不開的話題粪滤,它不僅是讀寫那么簡單斧拍,還涉及底層的文件系統(tǒng)和存儲設備。I/O 的快慢影響程序的執(zhí)行...
    落英墜露閱讀 2,955評論 0 3
  • 今天看到一位朋友寫的mysql筆記總結杖小,覺得寫的很詳細很用心肆汹,這里轉載一下,供大家參考下予权,也希望大家能關注他原文地...
    信仰與初衷閱讀 4,725評論 0 30