Android中如何優(yōu)化卡頓

本篇文章為大家展示了Android中如何優(yōu)化卡頓,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供朝陽網(wǎng)站建設、朝陽做網(wǎng)站、朝陽網(wǎng)站設計、朝陽網(wǎng)站制作等企業(yè)網(wǎng)站建設、網(wǎng)頁設計與制作、朝陽企業(yè)網(wǎng)站模板建站服務,十多年朝陽做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡服務。

  1. CPU 性能
    在開發(fā)過程中,我們可以通過下面的方法獲得設備的 CPU 信息。
    // 獲取 CPU 核心數(shù)
    cat /sys/devices/system/cpu/possible

    // 獲取某個 CPU 的頻率
    cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq

  2. 卡頓問題分析指標
    出現(xiàn)卡頓問題后,首先我們應該查看CPU 的使用率。怎么查呢?我們可以通過/proc/stat
    得到整個系統(tǒng)的 CPU 使用情況,通過/proc/[pid]/stat
    可以得到某個進程的 CPU 使用情況。
    關(guān)于 stat 文件各個屬性的含義和 CPU 使用率的計算,你可以閱讀《Linux 環(huán)境下進程的 CPU 占用率》和Linux 文檔。其中比較重要的字段有:
    proc/self/stat:
    utime:       用戶時間,反應用戶代碼執(zhí)行的耗時  
    stime:       系統(tǒng)時間,反應系統(tǒng)調(diào)用執(zhí)行的耗時
    majorFaults:需要硬盤拷貝的缺頁次數(shù)
    minorFaults:無需硬盤拷貝的缺頁次數(shù)

如果 CPU 使用率長期大于 60% ,表示系統(tǒng)處于繁忙狀態(tài),就需要進一步分析用戶時間和系統(tǒng)時間的比例。對于普通應用程序,系統(tǒng)時間不會長期高于 30%,如果超過這個值,我們就應該進一步檢查是 I/O 過多,還是其他的系統(tǒng)調(diào)用問題。
Android 是站在 Linux 巨人的肩膀上,雖然做了不少修改也砍掉了一些工具,但還是保留了很多有用的工具可以協(xié)助我們更容易地排查問題,這里我給你介紹幾個常用的命令。例如,top 命令可以幫助我們查看哪個進程是 CPU 的消耗大戶;vmstat 命令可以實時動態(tài)監(jiān)視操作系統(tǒng)的虛擬內(nèi)存和 CPU 活動;strace 命令可以跟蹤某個進程中所有的系統(tǒng)調(diào)用。
除了 CPU 的使用率,我們還需要查看CPU 飽和度。CPU 飽和度反映的是線程排隊等待 CPU 的情況,也就是 CPU 的負載情況。
CPU 飽和度首先會跟應用的線程數(shù)有關(guān),如果啟動的線程過多,容易導致系統(tǒng)不斷地切換執(zhí)行的線程,把大量的時間浪費在上下文切換,我們知道每一次 CPU 上下文切換都需要刷新寄存器和計數(shù)器,至少需要幾十納秒的時間。
我們可以通過使用vmstat
命令或者/proc/[pid]/schedstat
文件來查看 CPU 上下文切換次數(shù),這里特別需要注意nr_involuntary_switches
被動切換的次數(shù)。
proc/self/sched:
nr_voluntary_switches:    
主動上下文切換次數(shù),因為線程無法獲取所需資源導致上下文切換,最普遍的是 IO。    
nr_involuntary_switches:  
被動上下文切換次數(shù),線程被系統(tǒng)強制調(diào)度導致上下文切換,例如大量線程在搶占 CPU。
se.statistics.iowait_count:IO 等待的次數(shù)
se.statistics.iowait_sum:  IO 等待的時間

此外也可以通過 uptime 命令可以檢查 CPU 在 1 分鐘、5 分鐘和 15 分鐘內(nèi)的平均負載。比如一個 4 核的 CPU,如果當前平均負載是 8,這意味著每個 CPU 上有一個線程在運行,還有一個線程在等待。一般平均負載建議控制在“0.7 × 核數(shù)”以內(nèi)。
00:02:39 up 7 days, 46 min,  0 users,  
load average: 13.91, 14.70, 14.32

另外一個會影響 CPU 飽和度的是線程優(yōu)先級,線程優(yōu)先級會影響 Android 系統(tǒng)的調(diào)度策略,它主要由 nice 和 cgroup 類型共同決定。nice 值越低,搶占 CPU 時間片的能力越強。當 CPU 空閑時,線程的優(yōu)先級對執(zhí)行效率的影響并不會特別明顯,但在 CPU 繁忙的時候,線程調(diào)度會對執(zhí)行效率有非常大的影響。
關(guān)于線程優(yōu)先級,你需要注意是否存在高優(yōu)先級的線程空等低優(yōu)先級線程,例如主線程等待某個后臺線程的鎖。從應用程序的角度來看,無論是用戶時間、系統(tǒng)時間,還是等待 CPU 的調(diào)度,都是程序運行花費的時間。
Android 卡頓排查工具
Traceview 和 systrace 都是我們比較熟悉的排查卡頓的工具,從實現(xiàn)上這些工具分為兩個流派。
第一個流派是 instrument。獲取一段時間內(nèi)所有函數(shù)的調(diào)用過程,可以通過分析這段時間內(nèi)的函數(shù)調(diào)用流程,再進一步分析待優(yōu)化的點。
第二個流派是 sample。有選擇性或者采用抽樣的方式觀察某些函數(shù)調(diào)用過程,可以通過這些有限的信息推測出流程中的可疑點,然后再繼續(xù)細化分析。
這兩種流派有什么差異?我們在什么場景應該選擇哪種合適的工具呢?還有沒有其他有用的工具可以使用呢?下面我們一一來看。

  1. Traceview
    Traceview是我第一個使用的性能分析工具,也是吐槽的比較多的工具。它利用 Android Runtime 函數(shù)調(diào)用的 event 事件,將函數(shù)運行的耗時和調(diào)用關(guān)系寫入 trace 文件中。
    由此可見,Traceview 屬于 instrument 類型,它可以用來查看整個過程有哪些函數(shù)調(diào)用,但是工具本身帶來的性能開銷過大,有時無法反映真實的情況。比如一個函數(shù)本身的耗時是 1 秒,開啟 Traceview 后可能會變成 5 秒,而且這些函數(shù)的耗時變化并不是成比例放大。
    在 Android 5.0 之后,新增了startMethodTracingSampling
    方法,可以使用基于樣本的方式進行分析,以減少分析對運行時的性能影響。新增了 sample 類型后,就需要我們在開銷和信息豐富度之間做好權(quán)衡。

無論是哪種的 Traceview 對 release 包支持的都不太好,例如無法反混淆。其實 trace 文件的格式十分簡單,之前曾經(jīng)寫個一個小工具,支持通過 mapping 文件反混淆 trace。

  1. systrace
    systrace是 Android 4.1 新增的性能分析工具。我通常使用 systrace 跟蹤系統(tǒng)的 I/O 操作、CPU 負載、Surface 渲染、GC 等事件。
    systrace 利用了 Linux 的ftrace調(diào)試工具,相當于在系統(tǒng)各個關(guān)鍵位置都添加了一些性能探針,也就是在代碼里加了一些性能監(jiān)控的埋點。Android 在 ftrace 的基礎(chǔ)上封裝了atrace,并增加了更多特有的探針,例如 Graphics、Activity Manager、Dalvik VM、System Server 等。
    systrace 工具只能監(jiān)控特定系統(tǒng)調(diào)用的耗時情況,所以它是屬于 sample 類型,而且性能開銷非常低。但是它不支持應用程序代碼的耗時分析,所以在使用時有一些局限性。
    由于系統(tǒng)預留了Trace.beginSection
    接口來監(jiān)聽應用程序的調(diào)用耗時,那我們有沒有辦法在 systrace 上面自動增加應用程序的耗時分析呢?
    劃重點了,我們可以通過編譯時給每個函數(shù)插樁的方式來實現(xiàn),也就是在重要函數(shù)的入口和出口分別增加Trace.beginSection
    和Trace.endSection
    。當然出于性能的考慮,我們會過濾大部分指令數(shù)比較少的函數(shù),這樣就實現(xiàn)了在 systrace 基礎(chǔ)上增加應用程序耗時的監(jiān)控。通過這樣方式的好處有:
    ?   可以看到整個流程系統(tǒng)和應用程序的調(diào)用流程。包括系統(tǒng)關(guān)鍵線程的函數(shù)調(diào)用,例如渲染耗時、線程鎖,GC 耗時等。
    ?   性能損耗可以接受。由于過濾了大部分的短函數(shù),而且沒有放大 I/O,所以整個運行耗時不到原來的兩倍,基本可以反映真實情況。
    systrace 生成的是 HTML 格式的結(jié)果。

目前兩個工具都只支持 debugable 的應用程序,如果想測試 release 包,需要將測試機器 root。對于這個限制,我們在實踐中會專門打出 debugable 的測試包,然后自己實現(xiàn)針對 mapping 的反混淆功能。

隨著 Android 版本的演進,Google 不僅提供了更多的性能分析工具,而且也在慢慢優(yōu)化現(xiàn)有工具的體驗,使功能更強大、使用門檻更低。而 Android Studio 則肩負另外一個重任,那就是讓開發(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ā)者的使用門檻。
另外一個比較大的變化是分析結(jié)果的展示方式,這些分析工具都支持了 Call Chart 和 Flame Chart 兩種展示方式。下面我來講講這兩種展示方式適合的場景。

  1. Call Chart
    Call Chart 是 Traceview 和 systrace 默認使用的展示方式。它按照應用程序的函數(shù)執(zhí)行順序來展示,適合用于分析整個流程的調(diào)用。舉一個最簡單的例子,A 函數(shù)調(diào)用 B 函數(shù),B 函數(shù)調(diào)用 C 函數(shù),循環(huán)三次,就得到了下面的 Call Chart。

Call Chart 就像給應用程序做一個心電圖,我們可以看到在這一段時間內(nèi),各個線程的具體工作,比如是否存在線程間的鎖、主線程是否存在長時間的 I/O 操作、是否存在空閑等。

  1. Flame Chart
    Flame Chart 也就是大名鼎鼎的火焰圖。它跟 Call Chart 不同的是,F(xiàn)lame Chart 以一個全局的視野來看待一段時間的調(diào)用分布,它就像給應用程序拍 X 光片,可以很自然地把時間和空間兩個維度上的信息融合在一張圖上。上面函數(shù)調(diào)用的例子,換成火焰圖的展示結(jié)果如下。

當我們不想知道應用程序的整個調(diào)用流程,只想直觀看出哪些代碼路徑花費的 CPU 時間較多時,火焰圖就是一個非常好的選擇。例如,之前我的一個反序列化實現(xiàn)非常耗時,通過火焰圖發(fā)現(xiàn)耗時最多的是大量 Java 字符串的創(chuàng)建和拷貝,通過將核心實現(xiàn)轉(zhuǎn)為 Native,最終使性能提升了很多倍。

上述內(nèi)容就是Android中如何優(yōu)化卡頓,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

本文標題:Android中如何優(yōu)化卡頓
文章路徑:http://muchs.cn/article44/ghiche.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供服務器托管小程序開發(fā)、電子商務、網(wǎng)站設計公司、域名注冊、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務器托管