題記
1. 用戶對手機的需求層次
2. 穩定性
3. 續航
3.3.1 控制應用啟動
3.3.2 控制后臺進程運行
3.3.3 待機功耗優化
3.3.1 基礎功耗
3.1 更快的充電
3.2 更慢的耗電
3.3 待機功耗
3.4 場景功耗
4. 性能優化-流暢不卡頓
4.2.1 工具
4.2.2 app啟動優化
4.2.3 app運行優化
4.2.4 題外話
4.1.1 cpu優化
4.1.2 gpu優化
4.1.2 memory優化
4.1.3 io/disk和filesystem
4.1.4 網絡優化
4.1.2.1 優化內存分配算法
4.1.4.3.1 dns 問題
4.1.4.3.2 app
4.1.4.3.3 socket層
4.1.4.1 服務器端
4.1.4.2 傳輸路徑
4.1.4.3 應用層
4.1.4.4 傳輸層
4.1.4.5 鏈路層
4.1.4.6 終端:移動網絡和wifi
4.1 優化方向
4.2 場景優化
4.3 思路來源
5. 安全
6. 總結
8月,看到一個新聞:
攜手Unity引擎戰略合作:一加Ace Pro《原神》1小時59.3幀無壓力
感覺一加在上下游聯合優化方面,比其它友商晚了幾年。借此聊聊Android系統優化2008~2018這10年的事兒。
文章有點長,13000字,PC閱讀體驗要更好。感興趣的建議點贊收藏。??
功能齊全: 行業起步期
穩定不耗電: 行業發展期
性能流暢: 行業成熟期
安全:隱私問題會越來越重要
智能手機行業以蘋果發布第一代Iphone開端,乘著移動互聯網的東風,飛速發展。Google與此同時收購Android項目,自己主導開發。到Android 2.3時,國內雷軍帶領小米從做MIUI ROM轉做手機硬件,發布第一款互聯網營銷手機小米1代,小米1借助深耕很久的MIUI,成為當時國內功能最多樣的智能手機。但作為一個互聯網公司轉型做硬件,沒有華為、oppo、vivo這類硬件公司背景的技術積累。對軟件的穩定性的認識不夠,小米1 各種死機重啟。
隨著行業的發展,和iPhone的競爭,促使Android廠商在系統方面比拼cpu 頻率更快,memory內存更大,flash rom存儲空間更大;在外部設計上面,往屏幕方面更大尺寸,更高屏占比、更快的刷新頻率,指紋方面背面指紋解鎖,home鍵解鎖、屏下指紋解鎖發展。蘋果作為硬件背景公司,對mac os擴展為iOS系統后的各種tuning調優和深度整合,使得Android廠商過了好幾年才慢慢和iOS系統可以在同一水平。Android手機廠商對系統穩定性也足夠重視。
穩定性包括,os系統自身穩定性和三方app兼容性。google 每年發布更新Android大版本,自身的系統bug缺陷也是很多的。手機廠商自身OS功能開發也會引入各類bug。同時三方應用App由于對新版本的適配不及時,導致和新系統的兼容性問題也相當嚴重。尤其是各種保活黑科技的引入和動態升級更新熱修復。有些多進程保活方案,app自身代碼缺陷,導致一直fork創建新進程,甚至出現把linux kernel能使用的最大進程數量32768都用完,導致系統不能創建進程出現死機的情況,比如獵豹瀏覽器。熱修復方案以阿里的虛擬機dalvk和art虛擬機層hook方案和騰訊tinker方案為主流。阿里的風格比較激進,當然穩定性就差了些。騰訊的產品更看重穩定性,但少了些靈活。
手機廠商也設計出各種monkey測試、老化、壓測等各種自動化,各行各類應用 top 1000、top 2000、top 5000等兼容性自動化測試。華為等公司也開發了自己的云上系統,專門針對應用在華為手機上的穩定性進行強化壓力測試。
每次Android大版本升級,靠譜的手機廠商能發現各類問題缺陷上萬個。甚至出現專門bug-fix的工程師。
這么多問題,怎么處理呢?靠人分析人力投入遠遠不夠,就出現了各種監控,問題歸類,自動化提單,分析等技術。以期加快問題修復速度。
發展了這么多年,手機穩定性問題,慢慢成熟,一個Android手機,好幾個月也遇不到異常死機或者重啟問題。
但Android手機的電池續航一直很差。各個手機廠商也在續航尋求突破,比如華為資助研究石墨烯新材料。但是這個革命性技術是否成功,可能需要好多年的科研。畢竟還是在實驗室的玩具。一個技術性行不行,可以在實驗室進行科學論證研究。但是要變成商業產品,需要工程化,規模化,量產化。柔宇的柔性屏技術就遇到過量產良品率低導致成本高的問題。
延長手機續航時間有2個方向,讓用戶覺得:更慢的耗電和更快的充電。
2013、14年左右,一家做充電器的小廠商實驗完成了個大電流快速充電的設計,興致勃勃的找到各大手機廠商,由于產品穩定性等安全問題。碰了一鼻子灰。oppo的一個工程師知道這個方案后,很是喜歡,自個兒私下研究,通過設計各種危險情況判斷,多重模式切換阻斷,防止大電流,發熱,爆炸等,居然成功改進了各類問題,讓它更穩定,更安全。成就了2015年的“充電五分鐘,通話兩小時”。這項快充技術,讓oppo的產品在那年的差異化競爭嘗到甜頭,快充研發團隊獎勵了100萬。繼續研究,設計出了更快的閃充。中興移動(后面改名叫努比亞)相關領導想起oppo設計出的閃充和那家找過自己的小廠商,都后悔自己沒有深挖下去,錯過了這個機會。
電池容量E=電壓U x 電流I x 時間t。
電池容量比較固定,手機一般都3000+mAh,金立直接使用2塊電池解決大容量問題,算個例外;iPhone電池出現過2000+mAh的,但是人家軟硬一體化做得好,續航時長比Android系統要好,當然現在大屏,iPHone 11 好像是3500mAh左右。
oppo采用大電流方案并申請了專利,那高通、mtk、華為就走大電壓方案了。整個以前是5V x 4A的20W,發展到現在都40+W了。知乎上海出現過 到底是大電流安全還是大電壓安全 的問題。用了這么多年,國產手機好像沒出現過一次電池爆炸事件吧。當然,三星2016年出的電池爆炸事件可能是采用了比較激進的方案,對穩定性安全性重視不夠導致的手機行業大事件吧。
硬件上面的改進,不能替代軟件層面的優化。金山銀山,不好好持家,也會早晚敗光。
手機功耗包括3方面:
基礎功耗
待機功耗
場景功耗
手機硬件工程師會綜合考慮各個器件的布板(當然,高通、mtk一般會給個公板做參考)。出了整機后,軟件工程師還要對基礎功耗進行摸底排查,避免出現設計缺陷,出現漏電等情況。飛行模式下、亮度最低、音量mute等各種條件下,使用power monitor看關注的sensor、器件的電流到底有多大。
比如待機電流2mA左右;
比如wifi待機功耗比不開wifi大0.25mA;wifi搜網比不開wifi大2.5~4mA;
比如音頻最低音外放電流低于50mA;
...
如果發現異常,就要具體分析是什么原因。是因為漏電?還是 后臺在跑xx進程?
因為電量計算其實是個模擬電路的估算值,不能完全數字化那么準確。Android上采用計算各個sensor在不同模式下的電流情況,記錄到power_profiler.xml文件中,然后根據各個sensor運行的時長,繼續計算求和,得到估算的整體電量消耗存放在batterystats文件里面。這個方案存在不準確性,比如頻繁喚醒就可能出現實際電量消耗遠遠大于計算功耗。
開發電池計量器算法的工程師也會根據各個算法來優化實際電量消耗和狀態欄上的電量百分比的對應關系,因為電量和電量百分比這個不是一個線性關系。有些廠商會做個取巧的方案:90%以上的時候電量百分比變化慢,但實際電量消耗已經大于10%啦,讓算法在后續使用電量百分比的時候再慢慢平緩對應上。這也讓用戶避免出現剛充滿電,還沒怎么用就電量跌了這么多的心理不適。
電量的消耗是由于各個sensor硬件的運行,各個軟件進程、操作系統的cpu、gpu計算導致的。
針對待機功耗:就是讓手機不使用時候、滅屏后的功耗維持最低;使用時候,后臺跑層程序耗電最少。
由于Android的開放性和google服務在國內不能使用的原因,各個app為了保持服務器能及時發現app、通知app、控制app等,出現了各類進程保活方案。最讓人討厭的就是各類全家桶app相互喚醒,導致Android手機生態中的功耗問題相當嚴重。手機廠商就提出了各類自啟動控制、相互啟動控制等方案。
廠商直接在系統層面,對應用的廣播喚醒,provider喚醒、job scheduler喚醒,父子service喚醒,多進程監控喚醒、模擬binder調用喚醒等各類黑科技進行限制。
自身對功耗控制做的很好的微信等部分國民應用,廠商也愿意給它開白名單。所以就會出現,其它app公司的研發人員被產品業務"鄙視"為什么我們做不到自啟動,為啥微信可以做到?
國民級app和手機廠商的這種 相互綁架制約和相互平衡維持整個生態穩定也付出了重要貢獻。部分手機廠商甚至單獨出api接口給國民app,可以根據app自身運行場景進行動態調頻等功能。
Android圈還出現了 綠色公約,希望各個app加入維護好整個生態。
蘋果的iOS整體是封閉的,全部走蘋果自身的push推送,所以app保活這塊就比較風平浪靜。
控制功耗,自啟動控制能讓app不隨意運行,減少系統功耗;對于運行中的app,還可以通過限制后臺運行達到降低功耗的目的。
iOS系統,app退后臺后可以運行3分鐘左右(版本不同,策略不同),如果超時,就會被殺。如果遵守規則,就會類似signal - stop ,凍結進程。停止進程運行,達到減少系統耗電的目的。
Android上也要類似方案。2014、15年前,系統廠商主要采用定時清理進程、殺死后臺運行的進程,達到控制手機功耗的目的(還有個原因是當時手機內存不大,運行的應用多可能讓內存吃緊導致系統卡頓)。之后,出現了類似后臺凍結進程的方案,避免了粗暴的殺進程設計(但是針對異常耗電app,還是會采用kill方式,但可能會通知欄提示用戶xx-app耗電異常,可以考慮結束應用)。可以類似iOS的給進程發送stop信號,讓進程掛起;也可以采用linux本身支持的cgroups方案,直接把希望凍結的應用的所有進程加入cgroups的freezer組下面管控。
手機系統耗電,大頭在cpu上。對進程的調度,可以分當前應用、前臺應用、后臺應用等;android目前也采用分組進行控制。
cpu調度氛圍 調度器、調度策略、調度優先級等;由于Arm芯片有分大小核cpu,多核cpu等,進而可以讓后臺進程運行更低優先級;運行在小核,降低cpu頻率等降低功耗。對應當前應用,采用相反策略:
提高cpu頻率、按cpuset進行分組運行在打核、taskset設置親和性等 讓 用戶使用的app有盡可能多的cpu資源。
google EAS(Energy-Aware Scheduling)調度器方案,也是基于處理相同任務可以消耗更少的功耗,當然相同功耗,性能會更好。
EAS方案其實在幾年前有Linaro和Arm公司合作開發。Arm公司自己不生產cpu芯片,但它設計芯片,賣協議賣授權。iPhone和Android手機都是基于ARM cpu開發。而Linaro是一個在ARM平臺上連接公司企業和開源社區進行開發設計的組織。各個企業可以繳納不同的會費成為金牌銀牌贊助商。當然linaro會按贊助商的不同等級進行不同延期時間的同步內部的新技術新方案給他們。
Linux主流的CFS:'Completely Fair Scheduler' cpu公平調度調度策略是基于load負載和優先級-權重的的策略進行task任務的排序調度。優先級和權重其實就是些經驗值。進程優先級有0-139,前0-99位實時進程優先級;100-139位普通進程優先級,對應nice參數為-20-19。而權重對應普通優先級的nice值,nice越小優先級越高,對應權重也就越大。實時進程對應權重為nice=-20的2倍權重。調度器先調度實時進程隊列,再調度普通優先級隊列。
而EAS,不僅包括了CFS,還包括cpuidle、cpufreq。把各個零散的方案整合起來,綜合考慮。基于實際使用效能的調度策略。避免了原來依靠經驗值各種試錯tuning的方式,而是采用可測量的能效模型進行調優方法。
當然各個器件sensor也有自身的低功耗模式等,idle一小段時間可以自動suspend或者設置low power mode。
手機待機功耗異常,主要包括:
不能待機:包括應用端持鎖,kernel端持鎖;
頻繁喚醒:各類網絡請求,alarm等中斷喚醒ap;
子系統不待機:modem、gps、wifi、nfc等有在工作或發生suspend異常等;
google 設計的doze mode\device idle針對系統滅屏后一段時間后,針對非白名單應用,會限制網絡,取消wakelock避免系統不休眠,延遲alarm等各種定時任務同步、關閉wifi掃描等。App standby方案也是讓不常用的app被限制網絡等。但這類方案在中國大陸效果較差,app各類方案提高活躍度,比如某個音頻app為了做日活在埋點數據上還能作假翻幾倍,各個廠商還需要做中國特色的tuning增強完善。
其實除了google的這些個方案,廠商也早就研究基于不同用戶的app使用習慣,針對性的優化。數據顯示,一個用戶,常用app 一般不超過10個。針對這個特點,進行針對性優化。比如滅屏釋放waklock鎖、禁止gps location調用、關閉wifi 掃描或見啥掃描頻率,優化掃描算法避免無效的低信號質量wifi等。禁止app對某些頻繁變化的廣播響應,alarm對齊,網絡心跳喚醒對齊。對kernel層ap和子系統,大多數就是bug類,需要進行修復。比如,豌豆莢app曾經做過后臺靜音播放一個音頻文件,以期達到保活的目的,但是卻讓系統無法待機。還有些app出現1像素的activity保活奇葩方案。
所謂場景功耗優化,主要是針對用戶使用頻率較高的應用,比如主流游戲app、主流視頻、和社交app、camera。
功耗和性能是對天平的兩端,任何一端異常就讓產品失敗。所以各家也在找之間的平衡,有些產品主打性能,有些主打功耗。其實性能才是關鍵。app開發者也會面臨同樣的平衡。功耗也會像前面的穩定性問題一樣,變成一個產品的基礎體驗,各家差異不會太明顯。
要調優,就要找標準。可以和自己以前的產品對比,也可以和競品對比。比如A、B兩款手機,A手機玩王者榮耀電流500mA,但是有輕微卡頓;那么A款手機,電流可能有550mA,但是沒有卡頓。這個根據各家產品策略進行取舍。
通用優化方案:
app耗電主要包括:CPU、GPU、gps、audio等各個sensor。
cpu方案:運行cpu核數、綁定大小核、cpu頻率提頻等,保底最低fps等。
GPU方案:減少draw內容,針對app動態限制應用分辨率,這個在gpu上面的優化相當明顯。
GPS方案:合并多app上報頻率,動態上報頻率,待機禁止亂用;
app動態fps:除了控制cpu達到保底fps,可以通過各個應用適配性的動態fps,減少不必要的cpu、gpu消耗。卡頓主要不是由于fps低,而是由于fps不穩定,可以對比:電影24幀不卡頓,手機一般是60幀卻出現卡頓;unity游戲app一般都是動態fps,開發者可以配置。
屏幕高Hz功耗:由于90、120Hz高幀率做出了更流暢的體驗,但不是所有app都需要120Hz。針對不同app進行針對性的開啟或關閉高Hz,也能一定程度降低功耗。
屏幕: 數據刷新有performance和on-demand模式。
tp:固件優化采樣率、點擊坐標算法優化等。
針對特殊app,單獨優化:
減少layer:部分app多余layer,可以通過SurfaceFlinger進行移除。
長連接:微信等app長連接問題可以在kernel層進行netfilter過濾動態限制,減少同步頻率;
2015年之后,由于早期的野蠻發展,各類app的各類保活方案,讓國內的android生態比海外差好多。系統卡頓等問題層出不窮。各個廠商發布時候也重點突出自己的手機不卡頓,華為發布會號稱18個月不卡頓,側面反映出android手機出廠后系統調優很好,但是用久了,各類app讓手機系統的原有方案不生效了,卡頓也再次出現。
產品的性能優化,除了硬件方案,還包括軟件。
小米早期的宣傳文案就是使用了多少頻率的cpu、多少個cpu核、內存多大多大,比iPhone高多少多少。但實際情況還是沒iPhone流暢。當然iPhone每代產品也是會說cpu提升xx%, gpu性能提升xx%。手機硬件的提升,app也會越做越大越復雜,以期更好的利用硬件性能,那硬件的富余也可能會出現不足。
除了硬件方面一次性交易,軟件可以通過升級不對應對現實情況進行進一步調優。
2017年,蘋果公司的ipad pro 120Hz屏 給人驚艷的體驗。后續android也開始出現90Hz、120Hz屏。2020年,120Hz成了Android旗艦機標配。
其實性能優化涉及范圍最廣。android操作系統分層:
app-framework-native-|-kernel-driver-sensor/hardware
組件優化主要包括:CPU、gpu、flash disk、ddr memory、io、network;
流程優化主要包括:系統啟動優化、app啟動優化、app運行優化-卡頓jank優化;
當然,做app應用開發,性能穩定性等主要包括:cpu、gpu、memory、io、disk、network、卡頓、電量、穩定性、包大小,啟動速度、UI;部分其實有重合。
做性能優化,主要思路包括:
沒代碼,是最牛的優化--在階段去掉某些功能;
非關鍵邏輯,延后處理;
非關鍵邏輯,考慮提前執行;
關鍵邏輯,多線程,并發執行;
緩存部分結果,減少重復執行次數;
一次多操作,減少操作次數;
核心點:
別讓cpu、gpu閑著,不管是block,wait、還是本身就處于idle空閑狀態;關注多線程方案和鎖等待問題;
毫秒級別的優化,小數據的串行處理,可能比多線程異步流程還快,因為沒有任務調度延遲,比如tp觸摸屏的input事件;
大數據的流程邏輯,隊列、生產者消費者等異步化方案可能更穩定-削峰平谷,讓整個流程穩定輸出。-比如input事件在native層的處理:inputreader-inbound-inputdispatcher-outbound->transport;網卡驅動的buffer、ring長度、tcp的sync隊列、socket的sb_buffer隊列等;
更優的調度器:CFS主要針對的是服務器設置,各個任務的公平調度;而android其實更關注的是top-app當前應用的性能,其它后臺進程可以做適當的限制,Linaro的EAS更除了根據capacity容量的估算,還基于cluster按實際消耗進行調度優化。
開關cpu核心數量;
不同task任務綁定不同大小核:cpuset綁定獨占cpu核心,taskset綁定任務指定cpu核心運行;
控制cpu核心的頻率:governor 對cpu的電壓頻率進行控制;cpu的各種模式:on-demand、performance等
各個進程task根據不同的調度策略policy、優先級、進行cpu資源的動態占用,比如top-app、media進程等可能就需要設置較高的實時性策略;
cgroups的cpu控制能限制指定task任務組cpu資源的,比如限制后臺進程cpu使用率超過50%,開源節流-減少后臺浪費,給前臺任務更多資源。
開放接口給top-app,讓合作的app可以根據自身的場景切換設置不同的cpu使用策略,比如cpu boost;
配置dtsi,cpu超頻-為了性能;
以某款android手機為例:
支持的scaling_available_governors為
conservative ondemand userspace powersave performance schedutil
當前使用的governor是
schedutil
工具分析:
可以使用ftrace和systrace進行cpu使用情況分析,可以發現各個進程狀態、cpu狀態、cpu頻率繁忙和空閑情況等;但是它是基于埋點的方案。
基于sampling采樣方案;
基于instrument的方案:所有函數進入退出進行跟蹤;
hook方案:統計關鍵點的執行次數和時間;
轉火焰圖分析,快速發現系統瓶頸;
對app端來說,在cpu方面要多關注多線程問題,是否使用線程池,畢竟頻繁創建線程還是有開銷的,直接進行線程緩存,可以節約時間。線程數量是否太少,不能充分利用多核性能?是否太多造成調度延遲。
io密集型和cpu密集型的線程的需求其實不一樣:
cpu密集型,一般cpu-core + 1 個線程;如果系統把cpu資源都給你了,你要每個core都跑一個線程,留1個做備用應對任務調度;
io密集型,可能就要多啟動些線程,畢竟線程io block后,干不了其它事情,cpu都空閑出來了,增加線程可以增大搶占cpu的概率。
系統層面要關注cpu的飽和度,部分建議為cpu核心的0.7左右。具體還是要看實際測試情況。
android為了減少主線程任務,單獨起了RenderThread線程進行draw frame。
app ui響應input操作后,通過measure、layout、draw,把具體合成功能給gpu操作。
優化ui布局,或交互方式,減少layer層級和對象數量;
部分數據可以緩存,比如字體資源等,各類資源紋理等緩存cache可以適當tuning調大;
裁剪分辨率,減少數據量;
gpu的clock,頻率tuning;
gpu數據由串行改為并發執行;
Adreno和 mali 2類gpu本身調度算法性能優化;
android 開始使用skia軟件繪制,后面為了提高性能,引入gpu繪制;再后來引入vulkan。
內存不足可能會導致出現各種莫名其妙的問題;內存不足出現各種頁回收,碎片整理,swap交換。都可能導致卡頓。
維護系統可用內存最低閾值,減少卡頓
早期手機內存不大,一般采用kill殺后臺進程方案;后續內存大了,就更多采用的凍結方案。
android整合利用linux的lmk:low memory killer方案,在內存不足時殺優先級低的進程,根據不同內存閾值,進行查殺,直到恢復指定內存數量。但是默認參數在國內不適用,各家也自己tuning適配的參數。
lmk在app啟動階段,不要進行kill操作,這樣可以減少卡頓。
內存問題主要注意進程的內存泄漏,可以自己實現內存溢出監控-進程的絕對值和相對值/總內存的百分比閾值,也可以使用cgroups的內存控制功能實現。
注意:不要出現swap交換。
維護top app可用內存減少卡頓
app默認有最大heap使用限制,默認192MB。部分應用啟動需要消耗很多內存,超過gc閾值,就會觸發gc回收,造成卡頓。系統在app啟動時候,可用默認調高閾值,啟動完后退后臺再gc調整恢復閾值。
也可以結合cgroups的 memory模塊進行進程的內存限制。尤其是native的進程的限制,避免出現內存泄漏導致系統不穩定。
大型app,國民app也可以針對性的設置更大內存配額。減少gc卡頓。
后臺、待機時內存回收和碎片整理
內存問題,大多是容量不夠導致的問題。各類方案就是想方設法保證有充足的可用內存。
手機系統和傳統的pc或服務器系統的使用場景不一樣:
某時刻就那么幾個可見app,和1個top app,大部分都是后臺app進程;
手機有工作時間和待機時間--人總要睡覺。
內存優化,也可以基于性質,對后臺進程進行碎片整理;長時間待機時進行更激進的整體碎片整理和內存優化。disk的trim 也是利用這個特點進行待機碎片整理,也避免開機disk check的耗時。
kernel:
伙伴系統對大內存按page進行分配;
小內存按slub/slab分配;
內存碎片問題,系統運行一段時間后,ddr上留下各種各樣的空洞,導致alloc時連續空間不夠。
導致page compact頁面壓縮。
用戶層:
malloc的分配方案也很多:
高性能線程安全的:google 的tcmalloc、Facebook的jemalloc。
android使用dlmalloc和jemalloc;
tcmalloc:
類似kernel分配方案;
各個線程存有ThreadCache局部緩存,進程使用CentralCache中心緩存;
小對象走局部緩存:參考slub/slab 分成100+個class等級;
大對象走中心緩存:從1page,2pages、3pages,..數組+鏈表形式。
同時增加了回收功能;
jemalloc:
采用線程局部cache;
按大小分類small、large、huge;
采用chunk方式分割虛擬內存;
比tcmalloc開銷大點,性能好點;
用戶空間進程io系統調用到vfs虛擬文件系統;
vfs再標準化各類文件系統:ext4、f2fs等;
文件系統在對接generic block 塊設備;
block dev 發起讀寫請求高io調度器;
io調度器類似cpu的進程調度器,看能否合并某些page以期批量處理數據,減少磁盤io操作;
時機一到,觸發具體block的讀寫流程,交由各類塊設備driver驅動進行讀寫磁盤。
read大致流程:
發起system call,系統調用 轉到kernel內核態,用戶線程block阻塞等待;
vfs通過open時候的dirname找到inode對應的block上的位置返回fd,做個token標識。
通過讀取的文件offset偏移,找到磁盤block對應的物理頁映射到page cache緩存,方便下次直接讀取緩存,減少磁盤io開銷;
數據copy to user 系統調用返回進程,進程阻塞返回繼續執行;
write大致流程:
通過fd找到對應inode的對應offset的page緩存頁,沒有就先預讀加載進kernel;
更新數據到page cache,直接返回用戶進程;
kernel再選擇時機一起回寫到磁盤block,默認是5s;
block driver 是和disk配套的代碼控制器,完成block的讀寫和校驗,畢竟磁盤是死的。代碼才是活的。
參考方案:
新的更適合移動設備的flash規范,新的文件系統類型;
根據具體具體業務類型,選擇直接read/write, mmap,還是直接io等;
關注io操作的次數和buffer大小,按page大小倍速讀寫,可以減少io次數;
io調度器電梯算法的請求隊列和調度策略設置:cfs、noop、deadline;
順序io可以適當增大預讀size;
各類android 抓取log方案,就采用的是mmap方案,由于進程vma和kernel地址空間是共享的,可以減少1層系統調用開銷。
huawei: iotrace, io monitor
對app端來說,sqlite和shared preference性能影響較大。
sqlite的優化:
page大小、buffer大小;wal模式,關閉統計功能,mmap支持。
shared preference重寫優化:比如mmap方式替換;按uid通過binder進行本地server端更新。
不管是系統或者是app,網絡優化都相當重要。如果時不時來一下沒網或者網絡差,那這個產品可能沒賣不出去了。
網絡優化,主要關注吞吐量和延遲。重點場景為弱網和網絡擁塞。
數據在 終端-傳輸路徑-服務器 傳輸。網絡流程從下往上包括:
設備外的路由間轉發;
網卡收發數據;
網絡層ip;
傳輸層tcp、udp;
應用層;
客戶端按不同ip負載均衡,多數據中心,就近的數據中心,CDN;
有錢人用專線。終端到服務器中間可能經過各類路由器,要注意照顧最差的路由器的兼容性問題。
dns劫持比較多,app大多用httpdns;
dns預讀;
大公司服務器多,還會基于ip的地理位置進行就近返回。當然也會預制幾個服務器ip hash兜底,加快訪問速度。
android系統層做dns本地緩存,類似dnsmasq,結合各個app進行預緩存或app下載安裝時就做預解析,這個對app尤其是普通app冷啟動提速幫助很大。(但別破壞了大型app的客戶端做的負載均衡)。
有精力的手機廠商還可以底層監控不同gps位置,不同運營商、網絡類型(固網還是基站(gps+基站id))下的各個域名解析速度進行匯總分析,發展處第二曲線業務-dns服務商。
網絡庫:android的okhttp、iOS的AFNetwork。
目前很多公司基于chromium的net模塊-cronet(支持協議最全的開源網絡庫)進行定制化,比如減少https證書交換rtt、替換rsa為更快的加密算法等,同時配合服務器一起改造,做到0 rtt;httpdns定制等。--cronet最好有人牽頭做公共網絡庫,畢竟有些三方sdk公司不支持這個,也會影響app整體的網絡模塊定制。
壓縮數據、壓縮算法、請求合并、長連接代替短連接、多級緩存、epoll、aio、連接池、預連接、多路復用、spdy、quic、優先ipv6等;
單個socket的optmem_max緩沖區大小;
整個socket的發送接收緩沖區大小;
傳輸層的tcp/udp發送接收緩沖區范圍大小;
socket option可以控制的東西很多,除了timeout、buffer,還有TCP_NODELAY、TCP_CORK等。
關注/proc/sys/net/core/*;
還有一個重要問題:各類超時要針對移動網絡動態適配,快速超時快速重試,提升用戶可感知的體驗。
作為手機端的linux系統,不大可能出現服務器環境的高并發連接。它本身定位為客戶端,相關問題也會簡單很多,比如tcp的time_wait狀態過多等,當然android上可以按uid進行端口數量控制。tcp協議是最復雜,邊界問題最多的協議。
最簡單的比如tcp/udp的rmem、wmem 調整、tcp_synack_retries、tcp_fin_timeout、tcp_tw_reuse等。
長連接的tcp_keepalive_time、tcp_keepalive_intvl、tcp_keepalive_probes。
根據MTU動態調整包大小,減少分片。
其它的ip_local_port_range、調大fd數量。
其實tcp最開始是基于有線網絡低網速進行設計的,目前的網絡擁塞沖突算法在移動網絡場景不是特別優秀。google基于自身搜索引擎和youtube等實際業務的網絡監控分析,提出了tcp bbr擁塞控制算法,效果喜人。華為接入的multipath tcp已經使用bbr。
網卡硬中斷配置cpu親和性:/proc/irq/xxx/下的smp_affinity和smp_affinity_list;
irqbalance(默認每10s掃描interrupt情況,進行親和性重新設置);
軟中斷:RPS(Receive Packet Steering)hash packet的四元組到對應cpu,/sys/class/net/xx/queues/rx-0/rps_cpus;
軟中斷:RFS(Receive Flow Steering)按flow綁定cpu,提高緩存命中率:/proc/sys/net/core/rps_sock_flow_entries、/sys/class/net/xxx/queues/rx-0/rps_flow_cnt;
網卡的多隊列、隊列長度、buffer等;
cgroups net子系統按class和priority進行控制,~tc的qos;
協議層的部分功能下沉到網卡處理:TSO(TCP Segmentation Offload)和 UFO(UDP Fragmentation Offload)、GRO(Generic Receive Offload等。
參考dpdx xdp: kernel層邏輯上浮到user space和下沉到網卡;
由于手機系統的特殊性,定制化網卡是差異化競爭的一個亮點。
弱網:移動網絡相對有線網絡存在更大的不穩定性。弱網問題就相當嚴重。modem對小區的弱信號和小區擁塞分別進行不同的tuning,對弱信號的排除,失敗快速切換其它小區,小區禁用時間的重新設置。核心點:弱信號時快速試錯,擁塞時快速競爭占坑。
wifi: RF射頻天線的布局,rx\tx參數調優,提高發射功率和接收增益,wifi的EDCA\QoS\競爭窗口、速率選擇算法優化、wifi tcp buffer優化等。
監控接口網絡數據包的收發,錯誤、丟包等數據,動態切換網絡或增大功率等各類結構定制化優化方案。modem也可以根據gps和記錄等信息優先判斷適合的網絡類型,加速網絡建連。
systrace: 基于linux的ftrace進行改造的埋點跟蹤技術方案。原生是配置參數,抓取日志,chrome上分析。可以改進為在線實時分析方案。pc上在chrome上實現服務端(也可以使用node.js自己實現chrome的trace分析功能)。服務端進行開關動態配置,手機端通過網絡進行實時上傳trace日志,pc上就可以出現流式動態跟蹤數據,類似android studio的cpu profiler功能。
精簡版本的卡頓監控,可以打開cpu 等基本tag,檢查到卡頓自動dump trace日志上傳日志服務器。
可以通過looper,choreographer、gpu,renderthread、Surfaceflinger等卡頓監控點。
gpu工具:Adreno profiler 、mali debugger等工具。
perf、systemtap、dtrace等在android上的定制化應用。
apk redex優化;
盡量保證熱啟動;
啟動時候禁止kill,gc等耗時任務;
Launcher優先響應click事件,其它任務異步化或延遲執行;
view對click事件提前串行執行;
啟動動畫單獨設計和速率等調整,這個很影響速度;
app進程預創建和緩存-可以節約30-50ms左右;
耗時class預加載/異步加載;
app的renderthread等預先啟動,gpu等環境預先初始化和緩存-節約幾十ms;
app的theme、layout等和業務邏輯無關的資源可以預先load和緩存-可以節約上百ms;
app的lib so使用監控,預mmap;
系統層so合并和緩存,提升so加載速度;
app 減少不必要業務路徑,延遲不重要邏輯;
系統級dns緩存-可以節約100~400ms左右;
app啟動流程task化,充分利用多核cpu,避免鎖等待。
ams啟動大鎖優化,有限保證top-app和system_server各個核心線程占有cpu優勢資源;
各類boost和top-app的大核獨占綁定、優先級調高,后臺進程優先級調低;
非主activity等class,可以在startActivity后手動classloader.loadClass();
looper里消息分類和優先級:類型數組->優先級鏈表/數組->同優先級消息鏈表;
tp報點優化:縮短休眠喚醒間隔、提高采樣率,優化坐標計算算法;
不等sync信號,直接先處理input事件流程,點擊提前處理,滑動閾值、摩擦力參數優化,input也可以單獨線程處理;
view對click事件考慮串行不走post,click effect異步化或優先處理onclick;
子線程分擔ui線程input/../measure/layout任務-facebook方案可以參考;
app動態分辨率-部分app降低分辨率不影響體驗;
app自身各類listview\recycleview的item view細化緩存;
app自身layout優化,自定義層級、減少層級等;
framework層measure時動態優化不必要的viewgroups,減少層級;
view跨context緩存,切換activity時更新view的context相關內容;
gpu數據并行化;
SurfaceFlinger過濾多余layer,動態fps;
其它系統級:app線程的cpu核心綁定,cpu\gpu頻率,場景化boost,預留足夠內存,減少不必要的io,提高cpu、disk、net 優先級。irq balance。cgroups可以限制cpu、mem、disk 、net、io,要充分利用保證top-app優先使用。
注意thermal導致的限速降頻等;
整個系統為了高擴展性移植性等架構,多采用分層結構,但客制化對應的系統可以打破原有架構設計,根據top-app等android特有性能設計更好優先級、實時性的場景化方案,比如優先響應top-app的網絡請求,io請求等。
機器碼優化運行,減少字節碼解析運行--目前幾乎都是arm芯片,google可以考慮放棄通用性,單獨編譯成機器碼級別app。
其實,google現在也越來越關注開發者意見了。系統方可以開放2類api:
app啟動加速api:提供api給app 預加載緩存,提高冷啟動速度;
app運行調頻api: 微信把廠商提供給它的boost api封裝成Hardcoder也開源的;
國內android生態和國外完全兩碼。
后半段出現了微信等超級app,做的太好,以至于用戶會覺得出問了都是手機的問題,而不是微信app的問題,間接“綁架”手機廠商,導致微信在各個廠家幾乎都是各類白名單。超級app推出的小程序等,直接跳過app商店,導致分發廣告等收入提成的減少,這些事情都威脅到終端公司。
國內廠商組成的android聯盟,一方面要防止google的更深入的控制,一方面要避免硬件同質化和性能過剩沒有賣點,擔心為超級app做嫁衣,聯合起來切分國民app的蛋糕,步入互聯網化,慢慢達到國內android系統端的統一。
手機廠商由于有用戶的所有使用習慣,結合AI、大數據,進行用戶畫像,以更精準的提供千人千面的手機使用體驗。以各家推出的瀏覽器為例,雖然都是基于chromium瀏覽器改的,但是能更深入到系統層,提供比google的chrome更好的使用體驗,畢竟是站在巨人的肩上。當然也可以基于各自的上億用戶量,推出自己用戶的超級app--廠商玩這個就要差點火候了。
話題轉回來:而手機設備的后續的發展方向,會慢慢的項軟硬定制化深入,才能差異化。比如vivo花8000w和一加花1個億都和三星深度定制屏幕,跑在三星自己手機的前面了。比如這次的一加和Unity合作。比如以前的華為GPU定制,和王者榮耀合作。
思路比具體方案更重要:
app或系統自身的各類指標監控,關鍵點同步到服務端--標準產品研發邏輯;
用戶反饋問題專項攻關--能發現更廣更接近用戶的迫切問題;
各類方案借鑒:前端、后臺、移動端等的業務方向,同類產品思路的相互借鑒,app、framework、native、kernel、driver、硬件等層級方向;--跨界思考
逆向各類rom、app;專利分析,產品宣傳分析;
高薪招聘xx崗,面試友商相關人員,進行方案、思路獲取。
上下游合作:華為和王者榮耀合作,一加和游戲引擎廠商unity3d合作。
思路前2點屬于常規型;后3點屬于擴展型。
技術方案借鑒,是“跨界”的做技術思路。目前發現的好多方案都是在不同產品或系統平臺之間的相互切換移植參考。
Android 端有個好處是,都有公共的母版:google版本,然后才是其他oem rom,差異化分析相當簡單。對逆向分析競品幫助很大。是android平臺比較特有的思路。
而高薪招聘幌子則是比較難以防范的歪招。這個一般是實力弱的公司團隊招聘實力強的公司的人員才會用到。面試者為了證明自己能力,會對重點項目工作進行闡述,甚至細節公開。面試者可以說7分,留3分。7分里面的數據可以給大點誤差,3分主要包括大坑。如果真心招聘,入職再更正。如果惡意,會能誤導一部分。由于惡意招聘大多是低水平的團隊,這個應對方案他們一般也發現不了。
前面方案的目標都是為了找方向。找到方向后沉下去專項攻關,就需要團隊在各個方向都有專業人員儲備--術業有專攻。
各類軟件硬件安全問題,隱私問題會越來越重要。
出現過FPGA芯片安全漏洞,cpu指令重排漏洞,各類os系統、app等安全漏洞。
各個大公司因為隱私問題被罰款的案例也時有發生。
android rom 反編譯問題;
prop屬性按uid單獨獨立出來設計,加入pkgname和user group做鹽;
imei、mac等信息對app全部虛擬化,各個app獲取不同的固定值,用戶還可以手動不定時隨機刷新。
google版的android權限申請問題,被國內app濫用了,如果不給權限,app就退出。國內各廠商提供的passive permission control更適合隱私控制,app能正常使用,但是敏感權限控制可以拒絕某些數據讀取申請。
每年google 在春節左右會舉辦各個上下游廠商的內部camp,國內廠商可以反饋國內android生態的典型問題,推動google優化升級。
所有的手機產品,都是在找超出用戶預期、或者和友商差異化競爭的方案。從最開始的頻硬件產品、到后面功耗、性能等。有時候,不是有好方案,就馬上全上馬;而是研究行業發展趨勢,選取其中幾個有競爭性的點,搶占先發優勢,打動用戶,撇開競品。
聯想當時選取了防偽基站作為賣點,只討好了小部分的安全敏感、遇到過詐騙的用戶。
華為當年的xx turbo,其實就是各種小的優化點,帶來的大優化收益,不好講,就起名個唬人的turbo,有話題,有熱度,有賣點。
部分廠商,手機做得深的,會在某些方向引領產品方向,行業方向,國家標準方向。技術影響力也會輔助產品銷量。
能持續的賣出更多的好產品,獲取更大的利潤,才是手機產品能活下去的根本。
好奇今年的衛星短信功能能有多大助攻輔助華為、蘋果銷售。