回覆列表
  • 1 # APP開發那些事兒

    App執行速度分析以及初步最佳化方案

    一、 App執行速度分析

    (1)硬體約束

    CPU主頻,多核;

    CPU主頻決定手機的運算速度,多核則更多體現在併發任務方面。

    記憶體:運存與記憶體(RAM+ROM)

    圖1-1 移動端記憶體示例圖

    運存是指手機執行程式時的記憶體,也叫RAM簡稱運存;RAM越大,手機可執行的APP應用程式越多,執行越流暢,目前RAM基本是2GB夠用,3GB流暢,4GB極佳。

    記憶體是指手機的儲存控制元件,也叫ROM;ROM越大,手機儲存的檔案空間越多,目前ROM基本是16GB,32GB,64GB;ROM不影響手機的執行速度。

    當運存(RAM)匱乏時,執行大型APP會出現卡頓、黑屏甚至出現暫時性卡死狀態。

    在運存不夠時可以採取手動關閉後臺不必要的程式進行釋放,或者透過手機管理軟體進行記憶體釋放,例如手機管家、手機安全衛士等。

    (2)網路環境影響以及伺服器介面環境

    網路狀況直接影響業務型APP的體驗,例如使用者登陸業務;登陸時手機端需要向伺服器傳送使用者的登入名及密碼等資訊,伺服器進行資訊核對後返回登陸狀態指令,手機端接收到返回資訊進行業務跳轉。登陸業務只需要進行一次介面呼叫,在網路和伺服器環境都理想的情況下,http三次握手時間可以控制在1秒以內。綜合考慮手機端網路以及伺服器環境,登陸控制在2.5秒內是可以被使用者接受的。

    手機端針對網路環境可採取相應的快取策略以降低伺服器的頻繁訪問,從直觀上提高頁面響應速度。根據業務級別提供相對可靠的有損服務,可採用懶載入、延遲非同步載入等方式降低伺服器壓力。

    對於伺服器可採用快取伺服器、分散式伺服器、反向代理等方式進行資料提供業務,對於圖片、影片等媒體資源採用CDN進行加速。伺服器端的最佳化效能提高率遠大於手機端最佳化的提高率。

    (3)View的繪製過程

    Measure(計算) -> Layout(定位) -> Draw(繪製)

    整個View樹的繪圖流程是在ViewRoot.java類的performTraversals()函式展開的,函式做的執行過程可簡單概況為根據之前設定的狀態,判斷是否需要重新計算檢視大小(measure)、是否重新需要安置檢視的位置(layout)、以及是否需要重繪(draw),其框架過程如下:

    圖 1-2 View繪製流程示例圖

    View的繪製時間可以利用hierarchyviewer工具進行檢視。

    圖1-3 hierarchyviewer示例圖

    上圖Measure為0.089ms,Layout為0.115ms,Draw為1.088ms,該view的繪製總耗時為1.292ms。

    (4)16ms原則

    目前大多數手機的螢幕重新整理頻率是60hz,如果在1000/60=16.67ms內沒有辦法把這一幀的任務執行完畢,就會發生丟幀的現象。丟幀越多,使用者感受到的卡頓情況就越嚴重。16ms時間很短,身為一名應用開發者,為了讓使用者有更好的體驗,應該要充分利用這16ms,確保重新整理一幀的時候在16ms內。

    圖1-4 UI重新整理示例圖

    如果你的某個操作花費時間是24ms,系統在得到VSYNC訊號的時候就無法進行正常渲染,這樣就發生了丟幀現象。那麼使用者在32ms內看到的會是同一幀畫面。

    圖1-5丟幀示例圖

    最佳化16ms問題可以透過儘可能減少過度繪製,減少佈局巢狀,儘可能不要在UI執行緒做過多耗時操作。

    (5)OverDraw過度繪製

    當設計上追求更華麗的視覺效果的時候,我們就容易陷入採用複雜的多層次重疊檢視來實現這種視覺效果的怪圈。這這很容易導致大量的效能問題,為了獲得最佳的效能,我們必須儘量減少Overdraw的情況發生。

    圖 1-6 過度繪製四種級別示例圖

    藍色、淡綠、淡紅、深紅代表了4種不同程度的Overdraw情況,我們的目標就是儘量減少紅色Overdraw,看到更多的藍色區域。

    (6)GC垃圾回收

    GC一般耗時在幾毫秒到幾百毫秒之間,然而對於手機16ms渲染機制來說,GC會帶來不小的開銷,所以在開發過程中儘量避免顯示呼叫GC。頻繁GC會導致頁面卡頓,當執行GC操作時,任何執行緒都進入暫停狀態,等待GC操作結束後才能夠繼續執行。導致頻繁GC有兩個原因:

    1、 記憶體抖動,即大量的物件被建立後又在短時間內立刻被釋放

    2、 瞬間產生大量的物件會嚴重佔用Young Generation的記憶體區域,當達到閥值時會觸發GC過程。

    以上這些GC操作可能會造成丟幀情況,如下圖:

    圖 1-7 GC時丟幀示例圖

    24ms的GC形成了丟幀,使用者感知到頁面卡頓。

    (7)同步任務過多

    頁面啟動時同步任務過多會在短期內過多佔用手機資源,直接導致其他效能下降,影響頁面響應時間。例如在Activity的onCreate方法中進行了大量的同步任務。

    二、 初步最佳化方案

    綜上所述,App執行速度分析概括為以下七點:硬體約束、網路環境影響以及伺服器介面環境、View的繪製過程、16ms原則、OverDraw過度繪製、GC垃圾回收、同步任務過多。在這裡我們只對移動端開發並對後面五點提出相應的初步最佳化方案:非同步延遲載入。

    不妨先針對View的繪製過程、16ms原則來分析下某首頁,採用hierarchyviewer工具分析首頁如下:

    圖 2-1 首頁MLD分析示例圖

    從上圖可以看出首頁包含了1435個view,Measure耗時43.476ms,Layout耗時1.141ms,Draw耗時2.840,總耗時47.457ms(大於16ms)。基於16ms原則,該頁面會出現丟幀情況從而導致卡頓現象。針對這種長篇幅的頁面可以根據實際情況進行非同步延遲載入,對於第三屏、第四屏、第五屏採用梯級延遲載入從而避開同步載入。

    非同步延遲載入的關鍵是延遲時間為多少是合適的,對於配置較低的手機延遲相對要高一些,對於配置較高的手機延遲相對要低一些。如果延遲配置的不合理的話,高配置手機會產生等待延遲載入的內容的情況,而低配置手機會出現最佳化效果不明顯的情況。所以這個時間需要結合業務以及不同配置的手機進行測試來確定的。

    針對GC垃圾回收,我們以某APP MainActivity為例子分析下。MainActivity作為專案中所有Activity的託管,採用getLocalActivityManager().startActivity().getDecorView()方法獲取啟動Activity的檢視進行顯示。jumpActivity為切換Activity的方法,每次進行頁面跳轉時必須經過該方法,該方法包含GC過程。透過測試分析統計出每次跳轉頁面GC的耗時在8ms到300毫秒之間,這裡的GC時間會隨著下個啟動頁面的工作量越多而耗時越長。我們採用非同步處理一下,GC過程耗時在0~4ms之間,效果提升顯著。

    使用低配置的手機開啟某APP進入首頁時會黑屏8~·14秒,然後出現介面,透過程式碼分析發現首頁同步初始化五個重量級的Fragment,導致系統運存缺乏,影響了後續的介面繪製渲染等邏輯。我們採用非同步延遲載入進行處理一下,先對第一個主Fragment進行非同步載入,主Fragment載入完畢後再非同步載入第二個Fragment,接著第三個,最後第四個,這樣就可以在短時間內合理分配運存,避免了黑屏的情況。

    以上就是App執行速度分析以及初步最佳化方案,我們只有對App執行速度的硬體環境、開發的軟體因素以及App執行互動的原理進行了解後才能制定相應的最佳化方法,方可對症下藥。對於每一個可能影響使用者體驗的問題進行逐步最佳化,以先解決大問題、迫切問題為前提,以解決繁瑣、細小的問題為原則進行深入最佳化,App體驗才會越來越好。

  • 2 # 三袋大菠蘿

    作為開發者,在硬體基本確定的情況下。

    在應用層,應該避免資料重複讀寫。各種排序,查詢應選用較優演算法。最佳化大檔案的讀寫等。

    如果分為很多步驟啟動,應把每個步驟耗時記錄下來,並解決瓶頸步驟。

  • 中秋節和大豐收的關聯?
  • 100句英語諺語?