1. 程式人生 > >介面卡頓Jank與FPS獲取

介面卡頓Jank與FPS獲取

VSYNC 的概念

   VSYNC(Vertical Synchronization)是一個相當古老的概念,對於遊戲玩家,它有一個更加大名鼎鼎的中文名字—-垂直同步。
“垂直同步(vsync)”指的是顯示卡的輸出幀數和螢幕的垂直重新整理率相同,這完全是一個CRT顯示器上的概念。其實無論是VSYNC還是垂直同步這個名字,因為LCD根本就沒有垂直掃描的這種東西,因此這個名字本身已經沒有意義。但是基於歷史的原因,這個名稱在圖形影象領域被沿襲下來。
在當下,垂直同步的含義我們可以理解為,使得顯示卡生成幀的速度和螢幕重新整理的速度的保持一致。舉例來說,如果螢幕的重新整理率為60Hz,那麼生成幀的速度就應該被固定在1/60 s。

1.1 Android中的VSYNC

從Android 4.1開始,谷歌致力於解決Android系統中最飽受詬病的一個問題,滑動不如iOS流暢。因谷歌在4.1版本引入了一個重大的改進—Project Butter,也即是黃油計劃。
Project Butter對Android Display系統進行了重構,引入了三個核心元素,即VSYNC、Triple Buffer和Choreographer。這裡我們重點講解VSYNC的作用。

這個圖中有三個元素,Display是顯示螢幕,GPU和CPU負責渲染幀資料,每個幀以方框表示,並以數字進行編號,如0、1、2等等。VSync用於指導雙緩衝區的交換。
以時間的順序來看下將會發生的異常:
Step1. Display顯示第0幀資料,此時CPU和GPU渲染第1幀畫面,而且趕在Display顯示下一幀前完成。
Step2. 因為渲染及時,Display在第0幀顯示完成後,也就是第1個VSync後,正常顯示第1幀。
Step3. 由於某些原因,比如CPU資源被佔用,系統沒有及時地開始處理第2幀,直到第2個VSync快來前才開始處理。
Step4. 第2個VSync來時,由於第2幀資料還沒有準備就緒,顯示的還是第1幀。這種情況被Android開發組命名為“Jank”。
Step5. 當第2幀資料準備完成後,它並不會馬上被顯示,而是要等待下一個VSync。
所以總的來說,就是螢幕平白無故地多顯示了一次第1幀。原因大家應該都看到了,就是CPU沒有及時地開始著手處理第2幀的渲染工作,以致“延誤軍機”。

其實總結上面的這個情況之所以發生,首先的原因就在於第二幀沒有及時的繪製。我們將在三重緩衝一節中再講解這種情況)。那麼如何使得第二幀即使被繪製呢?
這就是我們在Graphic系統中引入VSYNC的原因,考慮下面這張圖:


如上圖所示,一旦VSync出現後,立刻就開始執行下一幀的繪製工作。這樣就可以大大降低Jank出現的概率。另外,VSYNC引入後,要求繪製也只能在收到VSYNC訊息之後才能進行,因此,也就杜絕了另外一種極端情況的出現—-CPU(GPU)一直不停的進行繪製,幀的生成速度高於螢幕的重新整理速度,導致生成的幀不能被顯示,只能丟棄,這樣就出現了丟幀的情況—-引入VSYNC後,繪製的速度就和螢幕重新整理的速度保持一致了。

   經過上面的介紹,希望讀者對Jank 和VSYNC有所認識。下面將說明怎麼來得到FPS和卡頓Jank幀數。

2 Jank 和 FPS

   我們只關注present time。


2.1 計算Janky frames


這裡的frame duration是有present time兩兩相減得到的。


由上圖可以得到jank 幀,右下角。

2.2 FPS


幀率(FPS)由present time的最後一幀減去第一幀得到時間值,然後除以幀數得到。

3 自動化獲取

自動化思路:使用python 結合uiautomator,根據配置資訊,啟動想評測的app,操作app(滑動,放大等等),列印surfaceflinger資料出來,稍微處理一下即可得到fps和掉幀數。

步驟:

(1)清理歷史資料

○ adb shell dumpsys SurfaceFlinger --latency-clear <window name>

(2)使用uiautomator操作某個APP

○ fling, scroll, zoom

(3)根據2操作,列印資料

○ adb shell dumpsys SurfaceFlinger --latency  <window name>

(4)處理資料

如讀者會使用Python的話,直接按照上面幾步即可得到FPS和Jank 數,因為邏輯已經很清晰了。本人寫的程式碼較多,這裡不附上說明。