您好,登錄后才能下訂單哦!
本篇文章為大家展示了Android中如何優(yōu)化卡頓,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
CPU 性能
在開發(fā)過程中,我們可以通過下面的方法獲得設(shè)備的 CPU 信息。
// 獲取 CPU 核心數(shù)
cat /sys/devices/system/cpu/possible
// 獲取某個(gè) CPU 的頻率
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
卡頓問題分析指標(biāo)
出現(xiàn)卡頓問題后,首先我們應(yīng)該查看CPU 的使用率。怎么查呢?我們可以通過/proc/stat
得到整個(gè)系統(tǒng)的 CPU 使用情況,通過/proc/[pid]/stat
可以得到某個(gè)進(jìn)程的 CPU 使用情況。
關(guān)于 stat 文件各個(gè)屬性的含義和 CPU 使用率的計(jì)算,你可以閱讀《Linux 環(huán)境下進(jìn)程的 CPU 占用率》和Linux 文檔。其中比較重要的字段有:
proc/self/stat:
utime: 用戶時(shí)間,反應(yīng)用戶代碼執(zhí)行的耗時(shí)
stime: 系統(tǒng)時(shí)間,反應(yīng)系統(tǒng)調(diào)用執(zhí)行的耗時(shí)
majorFaults:需要硬盤拷貝的缺頁次數(shù)
minorFaults:無需硬盤拷貝的缺頁次數(shù)
如果 CPU 使用率長期大于 60% ,表示系統(tǒng)處于繁忙狀態(tài),就需要進(jìn)一步分析用戶時(shí)間和系統(tǒng)時(shí)間的比例。對于普通應(yīng)用程序,系統(tǒng)時(shí)間不會(huì)長期高于 30%,如果超過這個(gè)值,我們就應(yīng)該進(jìn)一步檢查是 I/O 過多,還是其他的系統(tǒng)調(diào)用問題。
Android 是站在 Linux 巨人的肩膀上,雖然做了不少修改也砍掉了一些工具,但還是保留了很多有用的工具可以協(xié)助我們更容易地排查問題,這里我給你介紹幾個(gè)常用的命令。例如,top 命令可以幫助我們查看哪個(gè)進(jìn)程是 CPU 的消耗大戶;vmstat 命令可以實(shí)時(shí)動(dòng)態(tài)監(jiān)視操作系統(tǒng)的虛擬內(nèi)存和 CPU 活動(dòng);strace 命令可以跟蹤某個(gè)進(jìn)程中所有的系統(tǒng)調(diào)用。
除了 CPU 的使用率,我們還需要查看CPU 飽和度。CPU 飽和度反映的是線程排隊(duì)等待 CPU 的情況,也就是 CPU 的負(fù)載情況。
CPU 飽和度首先會(huì)跟應(yīng)用的線程數(shù)有關(guān),如果啟動(dòng)的線程過多,容易導(dǎo)致系統(tǒng)不斷地切換執(zhí)行的線程,把大量的時(shí)間浪費(fèi)在上下文切換,我們知道每一次 CPU 上下文切換都需要刷新寄存器和計(jì)數(shù)器,至少需要幾十納秒的時(shí)間。
我們可以通過使用vmstat
命令或者/proc/[pid]/schedstat
文件來查看 CPU 上下文切換次數(shù),這里特別需要注意nr_involuntary_switches
被動(dòng)切換的次數(shù)。
proc/self/sched:
nr_voluntary_switches:
主動(dòng)上下文切換次數(shù),因?yàn)榫€程無法獲取所需資源導(dǎo)致上下文切換,最普遍的是 IO。
nr_involuntary_switches:
被動(dòng)上下文切換次數(shù),線程被系統(tǒng)強(qiáng)制調(diào)度導(dǎo)致上下文切換,例如大量線程在搶占 CPU。
se.statistics.iowait_count:IO 等待的次數(shù)
se.statistics.iowait_sum: IO 等待的時(shí)間
此外也可以通過 uptime 命令可以檢查 CPU 在 1 分鐘、5 分鐘和 15 分鐘內(nèi)的平均負(fù)載。比如一個(gè) 4 核的 CPU,如果當(dāng)前平均負(fù)載是 8,這意味著每個(gè) CPU 上有一個(gè)線程在運(yùn)行,還有一個(gè)線程在等待。一般平均負(fù)載建議控制在“0.7 × 核數(shù)”以內(nèi)。
00:02:39 up 7 days, 46 min, 0 users,
load average: 13.91, 14.70, 14.32
另外一個(gè)會(huì)影響 CPU 飽和度的是線程優(yōu)先級,線程優(yōu)先級會(huì)影響 Android 系統(tǒng)的調(diào)度策略,它主要由 nice 和 cgroup 類型共同決定。nice 值越低,搶占 CPU 時(shí)間片的能力越強(qiáng)。當(dāng) CPU 空閑時(shí),線程的優(yōu)先級對執(zhí)行效率的影響并不會(huì)特別明顯,但在 CPU 繁忙的時(shí)候,線程調(diào)度會(huì)對執(zhí)行效率有非常大的影響。
關(guān)于線程優(yōu)先級,你需要注意是否存在高優(yōu)先級的線程空等低優(yōu)先級線程,例如主線程等待某個(gè)后臺線程的鎖。從應(yīng)用程序的角度來看,無論是用戶時(shí)間、系統(tǒng)時(shí)間,還是等待 CPU 的調(diào)度,都是程序運(yùn)行花費(fèi)的時(shí)間。
Android 卡頓排查工具
Traceview 和 systrace 都是我們比較熟悉的排查卡頓的工具,從實(shí)現(xiàn)上這些工具分為兩個(gè)流派。
第一個(gè)流派是 instrument。獲取一段時(shí)間內(nèi)所有函數(shù)的調(diào)用過程,可以通過分析這段時(shí)間內(nèi)的函數(shù)調(diào)用流程,再進(jìn)一步分析待優(yōu)化的點(diǎn)。
第二個(gè)流派是 sample。有選擇性或者采用抽樣的方式觀察某些函數(shù)調(diào)用過程,可以通過這些有限的信息推測出流程中的可疑點(diǎn),然后再繼續(xù)細(xì)化分析。
這兩種流派有什么差異?我們在什么場景應(yīng)該選擇哪種合適的工具呢?還有沒有其他有用的工具可以使用呢?下面我們一一來看。
Traceview
Traceview是我第一個(gè)使用的性能分析工具,也是吐槽的比較多的工具。它利用 Android Runtime 函數(shù)調(diào)用的 event 事件,將函數(shù)運(yùn)行的耗時(shí)和調(diào)用關(guān)系寫入 trace 文件中。
由此可見,Traceview 屬于 instrument 類型,它可以用來查看整個(gè)過程有哪些函數(shù)調(diào)用,但是工具本身帶來的性能開銷過大,有時(shí)無法反映真實(shí)的情況。比如一個(gè)函數(shù)本身的耗時(shí)是 1 秒,開啟 Traceview 后可能會(huì)變成 5 秒,而且這些函數(shù)的耗時(shí)變化并不是成比例放大。
在 Android 5.0 之后,新增了startMethodTracingSampling
方法,可以使用基于樣本的方式進(jìn)行分析,以減少分析對運(yùn)行時(shí)的性能影響。新增了 sample 類型后,就需要我們在開銷和信息豐富度之間做好權(quán)衡。
無論是哪種的 Traceview 對 release 包支持的都不太好,例如無法反混淆。其實(shí) trace 文件的格式十分簡單,之前曾經(jīng)寫個(gè)一個(gè)小工具,支持通過 mapping 文件反混淆 trace。
systrace
systrace是 Android 4.1 新增的性能分析工具。我通常使用 systrace 跟蹤系統(tǒng)的 I/O 操作、CPU 負(fù)載、Surface 渲染、GC 等事件。
systrace 利用了 Linux 的ftrace調(diào)試工具,相當(dāng)于在系統(tǒng)各個(gè)關(guān)鍵位置都添加了一些性能探針,也就是在代碼里加了一些性能監(jiān)控的埋點(diǎn)。Android 在 ftrace 的基礎(chǔ)上封裝了atrace,并增加了更多特有的探針,例如 Graphics、Activity Manager、Dalvik VM、System Server 等。
systrace 工具只能監(jiān)控特定系統(tǒng)調(diào)用的耗時(shí)情況,所以它是屬于 sample 類型,而且性能開銷非常低。但是它不支持應(yīng)用程序代碼的耗時(shí)分析,所以在使用時(shí)有一些局限性。
由于系統(tǒng)預(yù)留了Trace.beginSection
接口來監(jiān)聽?wèi)?yīng)用程序的調(diào)用耗時(shí),那我們有沒有辦法在 systrace 上面自動(dòng)增加應(yīng)用程序的耗時(shí)分析呢?
劃重點(diǎn)了,我們可以通過編譯時(shí)給每個(gè)函數(shù)插樁的方式來實(shí)現(xiàn),也就是在重要函數(shù)的入口和出口分別增加Trace.beginSection
和Trace.endSection
。當(dāng)然出于性能的考慮,我們會(huì)過濾大部分指令數(shù)比較少的函數(shù),這樣就實(shí)現(xiàn)了在 systrace 基礎(chǔ)上增加應(yīng)用程序耗時(shí)的監(jiān)控。通過這樣方式的好處有:
? 可以看到整個(gè)流程系統(tǒng)和應(yīng)用程序的調(diào)用流程。包括系統(tǒng)關(guān)鍵線程的函數(shù)調(diào)用,例如渲染耗時(shí)、線程鎖,GC 耗時(shí)等。
? 性能損耗可以接受。由于過濾了大部分的短函數(shù),而且沒有放大 I/O,所以整個(gè)運(yùn)行耗時(shí)不到原來的兩倍,基本可以反映真實(shí)情況。
systrace 生成的是 HTML 格式的結(jié)果。
目前兩個(gè)工具都只支持 debugable 的應(yīng)用程序,如果想測試 release 包,需要將測試機(jī)器 root。對于這個(gè)限制,我們在實(shí)踐中會(huì)專門打出 debugable 的測試包,然后自己實(shí)現(xiàn)針對 mapping 的反混淆功能。
隨著 Android 版本的演進(jìn),Google 不僅提供了更多的性能分析工具,而且也在慢慢優(yōu)化現(xiàn)有工具的體驗(yàn),使功能更強(qiáng)大、使用門檻更低。而 Android Studio 則肩負(fù)另外一個(gè)重任,那就是讓開發(fā)者使用起來更加簡單的,圖形界面也更加直觀。
在 Android Studio 3.2 的 Profiler 中直接集成了幾種性能分析工具,其中:
? Sample Java Methods 的功能類似于 Traceview 的 sample 類型。
? Trace Java Methods 的功能類似于 Traceview 的 instrument 類型。
? Trace System Calls 的功能類似于 systrace。
? SampleNative (API Level 26+) 的功能類似于 Simpleperf。
坦白來說,Profiler 界面在某些方面不如這些工具自帶的界面,支持配置的參數(shù)也不如命令行,不過 Profiler 的確大大降低了開發(fā)者的使用門檻。
另外一個(gè)比較大的變化是分析結(jié)果的展示方式,這些分析工具都支持了 Call Chart 和 Flame Chart 兩種展示方式。下面我來講講這兩種展示方式適合的場景。
Call Chart
Call Chart 是 Traceview 和 systrace 默認(rèn)使用的展示方式。它按照應(yīng)用程序的函數(shù)執(zhí)行順序來展示,適合用于分析整個(gè)流程的調(diào)用。舉一個(gè)最簡單的例子,A 函數(shù)調(diào)用 B 函數(shù),B 函數(shù)調(diào)用 C 函數(shù),循環(huán)三次,就得到了下面的 Call Chart。
Call Chart 就像給應(yīng)用程序做一個(gè)心電圖,我們可以看到在這一段時(shí)間內(nèi),各個(gè)線程的具體工作,比如是否存在線程間的鎖、主線程是否存在長時(shí)間的 I/O 操作、是否存在空閑等。
Flame Chart
Flame Chart 也就是大名鼎鼎的火焰圖。它跟 Call Chart 不同的是,F(xiàn)lame Chart 以一個(gè)全局的視野來看待一段時(shí)間的調(diào)用分布,它就像給應(yīng)用程序拍 X 光片,可以很自然地把時(shí)間和空間兩個(gè)維度上的信息融合在一張圖上。上面函數(shù)調(diào)用的例子,換成火焰圖的展示結(jié)果如下。
當(dāng)我們不想知道應(yīng)用程序的整個(gè)調(diào)用流程,只想直觀看出哪些代碼路徑花費(fèi)的 CPU 時(shí)間較多時(shí),火焰圖就是一個(gè)非常好的選擇。例如,之前我的一個(gè)反序列化實(shí)現(xiàn)非常耗時(shí),通過火焰圖發(fā)現(xiàn)耗時(shí)最多的是大量 Java 字符串的創(chuàng)建和拷貝,通過將核心實(shí)現(xiàn)轉(zhuǎn)為 Native,最終使性能提升了很多倍。
上述內(nèi)容就是Android中如何優(yōu)化卡頓,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。