<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android 顯示刷新機(jī)制、VSYNC和三重緩存機(jī)制

          共 4292字,需瀏覽 9分鐘

           ·

          2021-05-29 16:02

          和你一起終身學(xué)習(xí),這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識(shí)點(diǎn):

          一、刷新率與幀率
          二、Google 的優(yōu)化
          三、Triple Buffer三重緩存機(jī)制
          四、總結(jié)

          一、刷新率與幀率

          為了理解 APP 是如何進(jìn)行渲染的,我們就必須了解手機(jī)硬件是如何工作的,也必須理解什么是 VSYNC。

          首先,我們需要了解2個(gè)相關(guān)概念:

          1. 刷新率(Refresh Rate):

          代表了屏幕在一秒內(nèi)刷新屏幕的次數(shù),這取決于硬件的固定參數(shù),例如 60Hz。

          2. 幀率(Frame Rate)

          代表了 GPU 在一秒內(nèi)繪制操作的幀數(shù),例如 30fps,60fps。
          GPU 會(huì)獲取圖形數(shù)據(jù)進(jìn)行渲染,然后硬件負(fù)責(zé)把渲染后的內(nèi)容呈現(xiàn)到屏幕上,他們兩者不停的進(jìn)行協(xié)作。


          如果刷新率和幀率,各自做自己的事,不相互協(xié)調(diào)工作,那么刷新頻率和幀率并不總能夠保持相同的節(jié)奏。如果發(fā)生幀率與刷新頻率不一致的情況,就會(huì)容易出現(xiàn)畫面撕裂(Tearing)的現(xiàn)象,也就是畫面上下兩部分顯示內(nèi)容發(fā)生斷裂,來(lái)自不同的兩幀數(shù)據(jù)發(fā)生重疊。



          為了解決 Tearing 問題,Android 引入了 VSYNC 信號(hào)以及雙重與三重緩存機(jī)制。

          二、Google 的優(yōu)化

          從 Android 4.1 開始,谷歌致力于解決 Android 系統(tǒng)中最飽受詬病的一個(gè)問題,滑動(dòng)不如 iOS 流暢。因谷歌在 4.1 版本引入了一個(gè)重大的改進(jìn)—Project Butter,也即是黃油計(jì)劃。

          Project Butter 對(duì) Android Display 系統(tǒng)進(jìn)行了重構(gòu),引入了三個(gè)核心元素,即 VSYNC、Triple Buffer 和 Choreographer。Choreographer 在之前的文章《從源碼分析Choreographer是如何實(shí)現(xiàn)VSYNC信號(hào)的請(qǐng)求及幀的刷新處理?(Android Q)》中已經(jīng)分析過了,三重緩存機(jī)制我們后面介紹,這里我們重點(diǎn)講解 VSYNC 的作用。

          VSYNC(Vertical Synchronization)是一個(gè)相當(dāng)古老的概念,對(duì)于游戲玩家,它有一個(gè)更加大名鼎鼎的中文名字—-垂直同步。垂直同步(vsync)指的是顯卡的輸出幀數(shù)和屏幕的垂直刷新率相同。在當(dāng)下,垂直同步的含義我們可以理解為,使得顯卡生成幀的速度和屏幕刷新的速度的保持一致。舉例來(lái)說(shuō),如果屏幕的刷新率為 60Hz,那么生成幀的速度就應(yīng)該被固定在 16ms。

          上文中,我們已經(jīng)知道了什么事畫面撕裂(Tearing)現(xiàn)象以及它產(chǎn)生的原因,而 VSYNC 最重要的作用是防止出現(xiàn)畫面撕裂。

          VSYNC 信號(hào)是由屏幕(顯示設(shè)備)產(chǎn)生的,并且以 60fps 的固定頻率發(fā)送給 Android 系統(tǒng),Android 系統(tǒng)中的 SurfaceFlinger 接收發(fā)送的 VSYNC 信號(hào)。VSYNC 信號(hào)表明可對(duì)屏幕進(jìn)行刷新而不會(huì)產(chǎn)生撕裂。當(dāng) SurfaceFlinger 接收到 VSYNC 信號(hào)后,SurfaceFlinger 會(huì)遍歷其層列表,以查找新的緩沖區(qū)。如果 SurfaceFlinger 找到新的緩沖區(qū),SurfaceFlinger 會(huì)獲取緩沖區(qū);否則,SurfaceFlinger 會(huì)繼續(xù)使用上一次獲取的那個(gè)緩沖區(qū)。SurfaceFlinger 必須始終顯示內(nèi)容,因此它會(huì)保留一個(gè)緩沖區(qū)。如果在某個(gè)層上沒有提交緩沖區(qū),則該層會(huì)被忽略。

          通常來(lái)說(shuō),幀率超過刷新頻率只是一種理想的狀況,在超過 60fps 的情況下,GPU 所產(chǎn)生的幀數(shù)據(jù)會(huì)因?yàn)榈却?VSYNC 的刷新信息而被 Hold 住,這樣能夠保持每次刷新都有實(shí)際的新的數(shù)據(jù)可以顯示。但是我們遇到更多的情況是幀率小于刷新頻率。

          在這種情況下,某些幀顯示的畫面內(nèi)容就會(huì)與上一幀的畫面相同。糟糕的事情是,幀率從超過 60fps 突然掉到 60fps 以下,這樣就會(huì)發(fā)生 LAG,JANK,HITCHING 等卡頓掉幀的不順滑的情況。這也是用戶感受不好的原因所在。

          接下來(lái),我們以具體示例來(lái)看 VSYNC 的作用。

          1. 沒有使用 VSYNC 時(shí)

          我們來(lái)看沒有 VSYNC 的情況:

          這個(gè)圖中有三個(gè)元素,Display 是顯示屏幕,GPU 和 CPU 負(fù)責(zé)渲染幀數(shù)據(jù),每個(gè)幀以方框表示,并以數(shù)字進(jìn)行編號(hào),如0、1、2等等。

          CPU 正常執(zhí)行幀1,GPU 正常渲染幀1,所以幀1正常顯示。
          但,CPU 由于被占用等原因,等到即將顯示幀2時(shí),它才開始處理第二幀的內(nèi)容,這顯然完不成了,所以等到第二幀顯示的時(shí)候,只能使用上一幀的內(nèi)容顯示了,也即是丟幀了。
          上面丟幀的原因,我們可以從圖中看出,是因?yàn)樾碌囊粠_始的時(shí)候,CPU 在處理其他任務(wù),并沒有馬上執(zhí)行下一幀的任務(wù),那么如何讓 CPU 在新的一幀開始的時(shí)候立即處理顯示內(nèi)容呢?答案就在 VSYNC 身上!

          2.使用 VSYNC 信號(hào)

          我們來(lái)看,Android 引入 VSYNC 之后的幀執(zhí)行示意圖:

          第0幀顯示時(shí),CPU 和 GPU 準(zhǔn)備好了第一幀的內(nèi)容。
          第1幀剛開始顯示時(shí),CPU 放下手中的任務(wù),立馬處理第2幀顯示相關(guān)的任務(wù)(這里使用了消息屏障機(jī)制,可以參考前文《Android消息循環(huán)的同步屏障機(jī)制及UI渲染性能的提升(Android Q)》),這樣,在第二幀顯示之前, CPU 和 GPU 也提前完成了顯示任務(wù)的處理,第二幀正常顯示。
          可以看到,使用 VSYNC 信號(hào)機(jī)制,提升了渲染任務(wù)的優(yōu)先級(jí),優(yōu)化了渲染性能,可有效的減少了丟幀、卡頓等問題。

          但是上圖中仍然存在一個(gè)問題:CPU 和 GPU 處理數(shù)據(jù)的速度似乎都能在 16ms 內(nèi)完成,而且還有時(shí)間空余,也就是說(shuō),CPU 和 GPU 的幀率要高于 Display 的幀率。由于 CPU/GPU 只在收到 VSYNC 時(shí)才開始數(shù)據(jù)處理,故它們的幀率被拉低到與 Display 相同。但這種處理并沒有什么問題,因?yàn)?Android 設(shè)備的 Display FPS 一般是 60,其對(duì)應(yīng)的顯示效果非常平滑。

          但如果 CPU/GPU 的幀率小于 Display 的幀率,情況又不同了,將會(huì)發(fā)生如下圖的情況:


          在第二個(gè) 16ms 時(shí)間段,Display 本應(yīng)顯示 B 幀,但卻因?yàn)?GPU 還在處理 B 幀,導(dǎo)致 A 幀被重復(fù)顯示。
          同理,在第二個(gè) 16ms 時(shí)間段內(nèi),CPU 無(wú)所事事,因?yàn)?A Buffer 被 Display 在使用。B Buffer 被 GPU 在使用。注意,一旦過了 VSYNC 時(shí)間點(diǎn),CPU 就不能被觸發(fā)以處理繪制工作了。

          以上是使用雙重緩存機(jī)制時(shí)產(chǎn)生的問題,那么又如何來(lái)解決呢?

          為了解決這個(gè)問題,Android 引入了 Triple Buffer 機(jī)制。

          三、Triple Buffer三重緩存機(jī)制

          一般我們?cè)诶L制 UI 的時(shí)候,都會(huì)采用一種稱為“雙緩存”的技術(shù)(例如,上面幾個(gè)例子)。雙緩存意味著要使用兩個(gè)緩存區(qū),其中一個(gè)稱為 Front Buffer,另外一個(gè)稱為 Back Buffer。UI 總是先在 Back Buffer 中繪制,然后再和 Front Buffer 交換,渲染到顯示設(shè)備中。理想情況下,這樣一個(gè)刷新會(huì)在 16ms 內(nèi)完成,下圖就是描述的這樣一個(gè)刷新過程:Display 處理前 Front Buffer,CPU、GPU 處理 Back Buffer。

          只有兩個(gè) Buffer(Android 4.1之前)時(shí),CPU 在空閑時(shí),如果 Back Buffer 被占用了,它也只能等待 GPU 使用之后再次進(jìn)行寫入。我們可以想想,如果有第三個(gè) Buffer 的存在,CPU 是不是就可以提前工作,而不至于空閑了?所以,Google 在 Android4.1 以后,引入了三重緩存機(jī)制:Tripple Buffer。Tripple Buffer 利用 CPU/GPU 的空閑等待時(shí)間提前準(zhǔn)備好數(shù)據(jù),并不一定會(huì)使用。

          引入 Triple Buffer 效果如下圖所示:


          上圖中,第二個(gè) 16ms 時(shí)間段,CPU 使用 C Buffer 繪圖。雖然還是會(huì)多顯示 A 幀一次,但后續(xù)顯示就比較順暢了。

          那么,是不是 Buffer 越多越好呢?回答是否定的。由上圖可知,在第二個(gè)時(shí)間段內(nèi),CPU 繪制的第 C 幀數(shù)據(jù)要到第四個(gè) 16ms 才能顯示,這比雙 Buffer 情況多了 16ms 延遲,并且大量的緩存數(shù)據(jù)也會(huì)導(dǎo)致內(nèi)存增大,以及顯示數(shù)據(jù)是否失效等問題。所以,Buffer 三個(gè)足矣。

          四、總結(jié)

          刷新率(Refresh Rate):代表了屏幕在一秒內(nèi)刷新屏幕的次數(shù),這取決于硬件的固定參數(shù),例如 60Hz。

          幀率(Frame Rate):代表了 GPU 在一秒內(nèi)繪制操作的幀數(shù),例如 30fps,60fps。

          GPU 會(huì)獲取圖形數(shù)據(jù)進(jìn)行渲染,然后硬件負(fù)責(zé)把渲染后的內(nèi)容呈現(xiàn)到屏幕上,他們兩者不停的進(jìn)行協(xié)作。

          如果刷新率和幀率,各自做自己的事,不相互協(xié)調(diào)工作,那么刷新頻率和幀率并不總能夠保持相同的節(jié)奏。如果發(fā)生幀率與刷新頻率不一致的情況,就會(huì)容易出現(xiàn)畫面撕裂(Tearing)的現(xiàn)象。

          從 Android 4.1 開始,谷歌在黃油計(jì)劃中,引入了了三個(gè)核心元素,即 VSYNC、Triple Buffer 和 Choreographer。

          VSYNC 信號(hào)是由屏幕(顯示設(shè)備)產(chǎn)生的,并且以 60fps 的固定頻率發(fā)送給 Android 系統(tǒng),Android 系統(tǒng)中的 SurfaceFlinger 接收發(fā)送的 VSYNC 信號(hào)。VSYNC 信號(hào)表明可對(duì)屏幕進(jìn)行刷新而不會(huì)產(chǎn)生撕裂。

          使用 VSYNC 信號(hào)機(jī)制,提升了渲染任務(wù)的優(yōu)先級(jí),優(yōu)化了渲染性能,可有效的減少了丟幀、卡頓等問題。

          三重緩存機(jī)制(Triple Buffer) 利用 CPU/GPU 的空閑等待時(shí)間提前準(zhǔn)備好數(shù)據(jù),有效的提升了渲染性能。

          原文鏈接:https://blog.csdn.net/u011578734/article/details/110921266

          友情推薦:

          Android 開發(fā)干貨集錦

          至此,本篇已結(jié)束。轉(zhuǎn)載網(wǎng)絡(luò)的文章,小編覺得很優(yōu)秀,歡迎點(diǎn)擊閱讀原文,支持原創(chuàng)作者,如有侵權(quán),懇請(qǐng)聯(lián)系小編刪除,歡迎您的建議與指正。同時(shí)期待您的關(guān)注,感謝您的閱讀,謝謝!

          點(diǎn)個(gè)在看,方便您使用時(shí)快速查找!


          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级黄色免费片 | 亚洲狼友自拍 | 一级一片免费观看 | 看黑人免费操逼 | 国产午夜精品久久 |