Android高耗電場(chǎng)景分析

APP的噩夢(mèng)——“XXX正在后臺(tái)高耗電”

幾個(gè)場(chǎng)景

場(chǎng)景一:查查資料需纳,看個(gè)視頻芦倒,突然提示我:微信正在后臺(tái)高耗電!想想不翩,微信嘛兵扬,高耗電太正常了,把通知一關(guān)口蝠,該干啥干啥器钟。

場(chǎng)景二:支付寶付完款,放后臺(tái)干別的妙蔗,突然提示我:支付寶正在后臺(tái)高耗電傲霸!想想,支付寶高耗電也正常眉反,把進(jìn)程一殺昙啄,該干啥干啥。

場(chǎng)景三:要去哪個(gè)地方寸五,地圖導(dǎo)航完梳凛,放后臺(tái)。過段時(shí)間提示又來了:XX地圖正在后臺(tái)高耗電播歼!殺掉進(jìn)程,該干啥干啥掰读。

場(chǎng)景四:剛用完哪個(gè)不知名小APP秘狞,放后臺(tái),刷完朋友圈放松一下蹈集。我擦烁试,XXX正在高耗電,你誰(shuí)啊就敢耗我的電池拢肆,找出來减响,卸載靖诗。

某不知名APP開發(fā)者哭暈在廁所……

高耗電的危害

很多APP都遇到過后臺(tái)耗電的窘境,莫名其妙不知道發(fā)生了啥就被系統(tǒng)給黃牌警告支示。被提示耗電量高刊橘,會(huì)顯著降低用戶好感度,增加用戶卸載率颂鸿。一旦卸載促绵,任憑你功能多牛叉,體驗(yàn)多優(yōu)秀嘴纺,一切玩完败晴。

噩夢(mèng)的源頭——“Talk is cheap. Show me the code.”

要解決高耗電這一問題,得從源頭來分析栽渴。APP耗電分哪些部分尖坤,各是怎么計(jì)算的,才好對(duì)癥下藥闲擦,遠(yuǎn)離系統(tǒng)的黃牌警告慢味。

以android 25的代碼為例,計(jì)算APP耗電量的核心代碼是這個(gè)類——BatteryStatsHelper佛致,接下來我們一步步來分析贮缕。

里面有啥?

我們來看一下這個(gè)類有哪些成員變量俺榆,這個(gè)類的成員變量不多感昼,比較重要的有這些。

PowerCalculator mCpuPowerCalculator;

PowerCalculator mWakelockPowerCalculator;

MobileRadioPowerCalculator mMobileRadioPowerCalculator;

PowerCalculator mWifiPowerCalculator;

PowerCalculator mBluetoothPowerCalculator;

PowerCalculator mSensorPowerCalculator;

PowerCalculator mCameraPowerCalculator;

PowerCalculator mFlashlightPowerCalculator;

看這些變量名罐脊,是不是察覺到了什么定嗓?對(duì),這是系統(tǒng)對(duì)于不同維度耗電量的計(jì)算工具萍桌。

private PowerProfile mPowerProfile;

這個(gè)是對(duì)系統(tǒng)整個(gè)耗電情況的一個(gè)描述宵溅,比如CPU各頻段功耗、WIFI耗電情況上炎、藍(lán)牙耗電情況等恃逻。

private BatteryStats mStats;

這個(gè)成員提供了了對(duì)電源各項(xiàng)參數(shù)的訪問接口,諸如各進(jìn)程在cpu藕施、wakelock等方面的詳細(xì)耗電情況寇损,可以將耗電情況細(xì)化到進(jìn)程級(jí)別。

其余成員變量較多裳食,不再一一贅述矛市,有興趣的可以查看一下源碼。

耗電是咋計(jì)算的诲祸?

可以看到這個(gè)類對(duì)外提供了一系列的refreshStats()方法浊吏,跟進(jìn)查看一下而昨。

public void refreshStats(int statsType, SparseArray asUsers, long rawRealtimeUs,?long rawUptimeUs) {

? ? //初始化電源信息,各維度電量Calculator找田,以及時(shí)間參數(shù)

? ? …………

? ? //注意這個(gè)方法里會(huì)去詳細(xì)計(jì)算各維度的耗電量

? ? processAppUsage(asUsers);

? ? //計(jì)算完成后各uid的排序歌憨,以及格式化等操作

? ? …………

}

再看processAppUsage()方法

private void processAppUsage(SparseArray asUsers) {

? ? …………

? ? for(int iu =0;iu < NU; iu++) {

? ? ? ? finalUid u = uidStats.valueAt(iu);

? ? ? ? finalBatterySipper app =newBatterySipper(BatterySipper.DrainType.APP,u,0);

? ? ? ? mCpuPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mWakelockPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mMobileRadioPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mWifiPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mBluetoothPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mSensorPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mCameraPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? mFlashlightPowerCalculator.calculateApp(app,u,mRawRealtimeUs,mRawUptimeUs,mStatsType);

? ? ? ? …………

? ? ?}

? ? …………

}

可以看到,這里針對(duì)每個(gè)uid午阵,都計(jì)算了CPU/wakelock/移動(dòng)數(shù)據(jù)/WIFI數(shù)據(jù)/藍(lán)牙/傳感器/攝像頭/閃光燈八個(gè)維度的詳細(xì)電量信息躺孝,并做了排序。

水落石出

看到這里底桂,一切就清楚了植袍。APP耗電高,一定是這八個(gè)維度的某一方面消耗了大量電量籽懦。

(這里僅分析了APP耗電量的來源于个,具體的計(jì)算方法有興趣的讀者可以自行查看源碼)

捻手搭脈,對(duì)癥下藥

CPU耗電

CPU耗電主要分為以下幾個(gè)場(chǎng)景

進(jìn)程被頻繁拉起

大多數(shù)場(chǎng)景是存在不恰當(dāng)?shù)撵o態(tài)廣播注冊(cè)暮顺,導(dǎo)致進(jìn)程不斷被廣播拉起厅篓,產(chǎn)生一系列的初始化操作,不久又被ROM的省電策略所清理捶码,大量初始化不僅會(huì)造成大量CPU耗電羽氮,還有可能被ROM記錄為頻繁自啟甚至提示用戶,降低用戶好感度惫恼。

不恰當(dāng)?shù)膶?duì)外提供的ContentProvider與Service也存在這個(gè)問題档押。

如何定位:不同廠商的ROM有不同的啟動(dòng)日志,觀察APP的啟動(dòng)情況以及啟動(dòng)原因祈纯。

解決辦法:分析梳理上述場(chǎng)景令宿,并根據(jù)實(shí)際業(yè)務(wù)情況做清理與優(yōu)化。

高CPU占用率

由于CPU耗電分為多個(gè)不同的等級(jí)腕窥,低占用率耗電量比高占用率要低很多粒没。而在一些業(yè)務(wù)場(chǎng)景中,會(huì)存在非常高的CPU占用簇爆,比如大量IO/快速循環(huán)等癞松,會(huì)產(chǎn)生很高的耗電。

如何定位:利用top命令查看當(dāng)前包名下所有線程的CPU占用率入蛆,找出占用率很高的線程响蓉,分析這個(gè)線程在做什么。

解決辦法:根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景做優(yōu)化(利用緩存機(jī)制減少IO的次數(shù)安寺,快速循環(huán)里增加延時(shí)厕妖,或者直接重構(gòu)等)首尼。

低CPU占用率

這個(gè)場(chǎng)景比較復(fù)雜挑庶,比如有的動(dòng)畫機(jī)制是基于循環(huán)Handler的Message言秸,導(dǎo)致每隔一小段時(shí)間就會(huì)有CPU活動(dòng),久而久之也是不小的耗電量迎捺。

如何定位:這種場(chǎng)景下CPU占用率比較低举畸,無法直接找出對(duì)應(yīng)線程〉手Γ可采用MAT內(nèi)存分析工具抄沮,查看當(dāng)前內(nèi)存內(nèi)是否存在可疑的東西,比如大量堆積的Message等岖瑰。

解決辦法:按照實(shí)際問題與業(yè)務(wù)場(chǎng)景來做優(yōu)化叛买。

移動(dòng)數(shù)據(jù)&WIFI耗電

這兩個(gè)統(tǒng)稱流量耗電,耗電場(chǎng)景如下:

圖片/視頻加載

這是最常見的耗電場(chǎng)景蹋订,但是沒有什么特別好的辦法來解決率挣,如果圖片是由自身服務(wù)器配置的話,可以通過優(yōu)化圖片大小來減少流量消耗露戒。另外WIFI耗電是小于移動(dòng)數(shù)據(jù)耗電的椒功,大的圖片可以考慮在WIFI網(wǎng)絡(luò)下去加載。

服務(wù)器網(wǎng)絡(luò)請(qǐng)求

這種場(chǎng)景需要查看與服務(wù)器請(qǐng)求的時(shí)機(jī)是否不合理智什,或者過多动漾,服務(wù)器返回的消息內(nèi)容是否過長(zhǎng),并做相應(yīng)優(yōu)化荠锭。

其他耗電場(chǎng)景

其他的場(chǎng)景視各業(yè)務(wù)實(shí)際場(chǎng)景而定旱眯,整體思路是優(yōu)化耗電動(dòng)作的時(shí)機(jī),減少耗電動(dòng)作的次數(shù)节沦。

從噩夢(mèng)中醒來——“后記”

負(fù)責(zé)項(xiàng)目功耗專項(xiàng)也有大半年了键思,一開始手足無措,后來慢慢理清思路甫贯,開始鉆研源碼吼鳞,把耗電算法理解透。最后再分析代碼叫搁,從CPU/流量維度討論出了優(yōu)化方案赔桌,并最終修改解決。

最大的收獲是在源碼面前渴逻,一切BUG都無所遁形疾党。

關(guān)于耗電量的算法,這位仁兄研究要比我透徹得多惨奕,參考

http://www.reibang.com/p/27ba2759b221

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雪位,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梨撞,更是在濱河造成了極大的恐慌雹洗,老刑警劉巖香罐,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異时肿,居然都是意外死亡庇茫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門螃成,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旦签,“玉大人,你說我怎么就攤上這事寸宏∧牛” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵氮凝,是天一觀的道長(zhǎng)淋淀。 經(jīng)常有香客問我,道長(zhǎng)覆醇,這世上最難降的妖魔是什么朵纷? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮永脓,結(jié)果婚禮上袍辞,老公的妹妹穿的比我還像新娘。我一直安慰自己常摧,他們只是感情好搅吁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著落午,像睡著了一般谎懦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溃斋,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天界拦,我揣著相機(jī)與錄音,去河邊找鬼梗劫。 笑死享甸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的梳侨。 我是一名探鬼主播蛉威,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼走哺!你這毒婦竟也來了蚯嫌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎择示,沒想到半個(gè)月后妒牙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡对妄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敢朱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剪菱。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拴签,靈堂內(nèi)的尸體忽然破棺而出孝常,到底是詐尸還是另有隱情,我是刑警寧澤蚓哩,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布构灸,位于F島的核電站,受9級(jí)特大地震影響岸梨,放射性物質(zhì)發(fā)生泄漏喜颁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一曹阔、第九天 我趴在偏房一處隱蔽的房頂上張望半开。 院中可真熱鬧,春花似錦赃份、人聲如沸寂拆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纠永。三九已至,卻和暖如春谒拴,著一層夾襖步出監(jiān)牢的瞬間尝江,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工英上, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茂装,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓善延,卻偏偏與公主長(zhǎng)得像少态,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子易遣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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