renderthread是什么_Android 旗舰机标配的高帧屏(120Hz),对各位 App 开发者有什么影响?...
各大手機廠商發布的旗艦機,都將 90Hz 甚至 120Hz 高幀率流速屏當成了標配,那這對我們實際開發的 App 會不會有影響?原本在 60Hz 下,每幀只需保證 16ms 內繪制完成就可以做到流暢,換到高幀屏中,實際留給我們繪制時間是縮短了的,是否對我們的代碼質量要求更高?
推薦一篇文章,來講講對此的影響,希望對大家有幫助。
以下文內的 "我" 為文章原作者。
前言
昨天在 IT 之家留言說,如果應用無法滿足 120hz 的繪制會怎樣?假設如果繪制一幀的時間,如果大于 1/120 秒,哪怕是多了 1 毫秒,就會導致應用在 120Hz 的手機上也就變成了 60Hz。
后來仔細想想,這句話說的并不是特別嚴謹,為什么這么說呢?
一、證明我的觀點
首先我寫一個 demo 來證明我的觀點。
1.1 滿幀的應用
public class MyTextView extends TextView {int i = 0; @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (i < 6) {
this.post(new Runnable() {
@Override
public void run() {
MyTextView.this.setText(i++ + "");
}
});
}
}
}
我寫了一個只繪制 6 幀的一個界面,Activity 中包含這個 MyTextView,通過抓 Trace 可以看到,下面這個 6 幀繪制圖,都是在一個 Vsync 周期(圖中黑白相見的色塊,均是一個 Vsync 周期)繪制一幀。
為什么第一幀會有點延遲,主要是因為啟動時,主線程在干了些其他事情,好在繪制花不了太多時間。
大概繪制也就 3 毫秒左右,畢竟界面簡單。
1.2 幀數減半的應用
public class MyTextView extends TextView {int i = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
try {
Thread.sleep(16);
} catch (Exception e) {
}
if (i < 6) {
this.post(new Runnable() {
@Override
public void run() {
MyTextView.this.setText(i++ + "");
}
});
}
}
}
我手動人為在 MyTextView.onDraw() 方法中 sleep 了 16 毫秒,來模擬很多應用實現的不好,導致繪制耗時的情況,例如 View 層級厲害復雜,甚至在 onDraw() 方法中進行文件讀寫。
通過抓 trace 可以看到,原本之前的例子(1.1)中 6 幀由 6 個時間周期繪制完成,現在變成了 6 幀由 12 個時間周期完成了。
1.3 小結
這就是我一直想說的一個觀點,120Hz 的手機體驗不一定有 90Hz 的手機好的原因,一旦主線程一次 traversal(一次 ViewRootImpl 的 onDraw() 的遍歷)的時間超出了 vsync 的時間周期 1/120s,就會導致幀率直接砍半,降為 60 幀,90Hz 可以讓這個折半降幀率的現象減少。
二、繪制一幀指的是什么
為什么我說我的觀點不準確?其實是我太籠統的定義了繪制一幀這個詞。
在硬件加速開啟的情況下:
- 如果我將繪制一幀的時間定義成:主線程一次 traversal,那我說的話是正確的。
- 如果我將繪制一幀的時間定義成:主線程一次 traversal + renderthread 一次渲染,那我說的話是不嚴謹的。
2.1 引發我思考的 trace
因為要讓主線程一次 traversal + renderthread 超時不是特別好寫 demo,我就用一個昨天引發我思考的一個 trace 給大家講解一下。
大家從第一個黃色 F 的圓圈開始看。
UI Thread 的 doFrame + RenderThread 的 DrawFrame 的時間超出了一個 Vsync 周期,接下來每一幀的情況,都是按照第一幀繪制的情況一樣的情況運行,最好造成的現象就是雖然幀數是滿幀,但是每一幀其實都是延遲顯示的。
用一句哲學的話來概括就是:你眼睛看到任何事物,其實都是事物過去的樣子。
假如主線程一次 traversal + renderthread 一次渲染時間超出了 vsync 周期不多,這樣子的應用大概率是可以滿幀運行(滿幀不代表顯示正常)。
我上面一句話中用了不多,大概率這種模糊的文字,因為這個情況下能否滿幀的臨界點比較難定義。
2.2 如何定義這個 120 變成 60 幀的臨界點
繼續下面這個圖,你會發現 UI Thread 的 doFrame 會非常 happy 的按照 Vsync 信號執行,但是下面 renderthread 已經忙的不可開交了。
其實第一幀已經延遲了,假如運氣不好導致了 drawframe 的時間橫跨了 2 個 Vsync 周期,還是會導致丟幀,這個時候就從 120 幀降為 60 幀。
三、總結
3.1 理想中的結論
假設開啟硬件加速,一幀繪制的時間 = UI 線程(T1)+ RenderThread 線程(T2)。
那么 Vsync 時間的周期是 1/120s,約等于 8.3ms,此時:
- 如果 16.6ms > T1 > 8.3ms,會導致從 120 幀降為 60 幀。
- 如果 T1 <8.3ms,16.6ms> T1 + T2 > 8.3ms,雖然還是滿幀,但是你看到的永遠是前一幀的畫面。
- 如果 T1 + T2 > 16.6ms,毫無疑問會導致從 120 幀降為 60 幀。
上面理論看起來是很完美的結論,千萬別把這個當做定理去記憶,因為現實會比這些情況復雜的多。
3.2 顯示中的結論
可能會有人說現在 CPU,GPU 那么強,怎么可能會超時呢?
舉個微信在 865 的手機上,滑動消息列表的例子,T1 約等于 6ms,T1 + T2 約等于 8.2ms。
這還并不是太過復雜的界面,大家會發現,6ms 已經很接近 8.3ms 了。
3.3 給開發者的建議
對于要適配 120hz 手機的應用的工程師,你們要注意以下事情。
四、尾巴
說到這里,如果聽得懂我在說什么的人,應該能懂我想表達的意思。
如果不懂我說的什么的人,希望你去補一下以下知識點,再回過頭來看這個文章。
知識點 1:
TextView.setText 到屏幕顯示文字,整個過程發生了什么。
知識點 2:
硬件加速之后,主線程(UI Thread)和 RenderThread 之間的協同工作的方式。
知識點 3:
APP 界面和 SurfaceFlinger 之間的關系
可能會有人說,你揪那么細致干嘛,對于用戶來說,掉了幾幀的影響也不大,,但是對于性能優化工程師來說,有時候就是要糾結那幾個丟幀的情況,只有做好了每一幀的完美繪制,才能給用戶帶來最完美的用戶體驗。
- End -
文章看完了,最后我換個角度補充一些觀點。
手機硬件雖然增加了高幀屏,確實看似對每一幀繪制的時間要求更短了,但別忘了,在升級屏幕的同時,對其他硬件(CPU、GPU、ROM等)也做了相應的升級。雖然留給我們的刷新時間縮短了,但計算和渲染繪制的能力,也相應的提高了。
那么到具體的代碼上,你在舊手機上繪制一幀需要 10ms 的代碼,在 120Hz 的旗艦機上可能只需要 6ms,兩相抵消之下問題不會太大。
所以最后核心還是在日常編碼的過程中,隨時注意性能的問題。管他高幀低幀,領導覺得"不跟手",咱就嘚優化。
本文對你有幫助嗎?留言、轉發、點好看是最大的支持,謝謝!
公眾號后臺回復成長『成長』,將會得到我準備的學習資料。
總結
以上是生活随笔為你收集整理的renderthread是什么_Android 旗舰机标配的高帧屏(120Hz),对各位 App 开发者有什么影响?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像归一化处理 相同像素_图像处理学习笔
- 下一篇: cmd oracle 连接实例_基于wi