<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      安卓筆記俠

      專注安卓開發(fā)

      導(dǎo)航

      Android繪制優(yōu)化(一)繪制性能分析

      前言

      一個優(yōu)秀的應(yīng)用不僅僅是要有吸引人的功能和交互,同時在性能上也有很高的要求。運行Android系統(tǒng)的手機,雖然配置在不斷的提升,但仍舊無法和PC相比,無法做到PC那樣擁有超大的內(nèi)存以及高性能的CPU,因此在開發(fā)Android應(yīng)用程序時也不可能無限制的使用CPU和內(nèi)存,如果對CPU和內(nèi)存使用不當(dāng)也會造成應(yīng)用的卡頓和內(nèi)存溢出等問題。因此,應(yīng)用的性能優(yōu)化對于開發(fā)人員有著更高的要求。Android性能優(yōu)化分為很多種,比較常用的有繪制優(yōu)化、內(nèi)存優(yōu)化、耗電優(yōu)化和穩(wěn)定性優(yōu)化等,這個系列我們就來學(xué)習(xí)性能優(yōu)化中的繪制優(yōu)化。

      1.繪制原理

      Android繪制View有三個主要的步驟,分別是measure、layout和draw。關(guān)于它們的原理請查看我的文章Android View體系(七)從源碼解析View的measure流程Android View體系(八)從源碼解析View的layout和draw流程,這里就不在贅述。measure、layout和draw方法主要是運行在系統(tǒng)的應(yīng)用框架層,而真正將數(shù)據(jù)渲染到屏幕上的則是系統(tǒng)Nativie層的SurfaceFlinger服務(wù)來完成的。

      繪制過程主要是由CPU 來進行Measure、Layout、Record、Execute的數(shù)據(jù)計算工作,GPU負(fù)責(zé)柵格化、渲染。CPU和GPU是通過圖形驅(qū)動層來進行連接的。圖形驅(qū)動層維護了一個隊列,CPU將display list添加到該隊列中,這樣GPU就可以從這個隊列中取出數(shù)據(jù)進行繪制。

      1.1 渲染時間線

      FPS(Frames Per Second)這個名詞我想很多同學(xué)都知道,它是指畫面每秒傳輸幀數(shù),通俗來講就是指動畫或視頻的畫面數(shù),最簡單的舉例就是我們玩游戲時,如果畫面在60fps則不會感覺到卡頓,如果低于60fps,比如50fps則會感覺到卡頓,你就可以考慮要換顯卡或者采取其他一些措施了。
      要想畫面保持在60fps,則需要每個繪制時長在16ms以內(nèi),如下圖所示。

      04080416_dgEb.png

      Android系統(tǒng)每隔16ms發(fā)出VSYNC信號,觸發(fā)對UI進行渲染, 如果每次渲染都成功,這樣就能夠達(dá)到流暢的畫面所需要的60fps,那什么是VSYNC呢?VSYNC是Vertical Synchronization(垂直同步)的縮寫,是一種定時中斷,一旦收到VSYNC信號,CPU就開始處理各幀數(shù)據(jù)。
      如果某個操作要花費24ms,這樣系統(tǒng)在得到VSYNC信號時無法進行正常的渲染,會發(fā)生丟幀。用戶會在32ms中看到同一幀的畫面,如下圖所示。

      04080416_cWwX.png

      產(chǎn)生卡頓原因有很多,主要有以下幾點:

      • 布局Layout過于復(fù)雜,無法在16ms內(nèi)完成渲染。
      • 同一時間動畫執(zhí)行的次數(shù)過多,導(dǎo)致CPU或GPU負(fù)載過重。
      • View過度繪制,導(dǎo)致某些像素在同一幀時間內(nèi)被繪制多次。
      • UI線程中做了稍微耗時的操作。

      為了解決上述的問題,除了我們要在寫代碼時要注意外,也可以借助一些工具來分析和解決卡頓問題。

      2.Profile GPU Rendering

      Profile GPU Rendering是Android 4.1系統(tǒng)提供的開發(fā)輔助功能,我們可以在開發(fā)者選項中打開這一功能,如下圖所示。

      打開Profile GPU Rendering_副本_副本.png打開Profile GPU Rendering_副本_副本.png
      我們點擊Profile GPU Rendering選項并選擇On screen as bars即開啟Profile GPU Rendering功能。接著屏幕會顯示出彩色的柱狀圖,如下所示。

      Screenshot_20170308-152841_副本.png
      上面的彩色的圖的橫軸代表時間,縱軸表示某一幀的耗時。綠色的橫線為警戒線,超過這條線則意味著時長超過了16m,盡量要保證垂直的彩色柱狀圖保持在綠線下面。這些垂直的彩色柱狀圖代表著一幀,不同顏色的彩色柱狀圖代表不同的含義:

      • 橙色代表處理的時間,是CPU告訴GPU渲染一幀的地方,這是一個阻塞調(diào)用,因為CPU會一直等待GPU發(fā)出接到命令的回復(fù),如果橙色柱狀圖很高,則表明GPU很繁忙。
      • 紅色代表執(zhí)行的時間,這部分是Android進行2D渲染 Display List的時間。如果紅色柱狀圖很高,可能是由重新提交了視圖而導(dǎo)致的。還有復(fù)雜的自定義View也會導(dǎo)致紅的柱狀圖變高。
      • 藍(lán)色代表測量繪制的時間,也就是需要多長時間去創(chuàng)建和更新DisplayList。如果藍(lán)色柱狀圖很高,可能是需要重新繪制,或者View的onDraw方法處理事情太多。

      在Android 6.0中,有更多的顏色被加了進來,如下圖所示:
      QQ截圖20170320133358.png

      下面來分別介紹它們的含義:

      • Swap Buffers:表示處理的時間,和上面講到的橙色一樣。
      • Command Issue:表示執(zhí)行的時間,和上面講到的紅色一樣。
      • Sync & Upload:表示的是準(zhǔn)備當(dāng)前界面上有待繪制的圖片所耗費的時間,為了減少該段區(qū)域的執(zhí)行時間,我們可以減少屏幕上的圖片數(shù)量或者是縮小圖片的大小。
      • Draw:表示測量和繪制視圖列表所需要的時間,和上面講到的藍(lán)色一樣。
      • Measure/Layout:表示布局的onMeasure與onLayout所花費的時間,一旦時間過長,就需要仔細(xì)檢查自己的布局是不是存在嚴(yán)重的性能問題。
      • Animation:表示計算執(zhí)行動畫所需要花費的時間,包含的動畫有ObjectAnimator,ViewPropertyAnimator,Transition等。一旦這里的執(zhí)行時間過長,就需要檢查是不是使用了非官方的動畫工具或者是檢查動畫執(zhí)行的過程中是不是觸發(fā)了讀寫操作等等。
      • Input Handling:表示系統(tǒng)處理輸入事件所耗費的時間,粗略等于對事件處理方法所執(zhí)行的時間。一旦執(zhí)行時間過長,意味著在處理用戶的輸入事件的地方執(zhí)行了復(fù)雜的操作。
      • Misc Time/Vsync Delay:表示在主線程執(zhí)行了太多的任務(wù),導(dǎo)致UI渲染跟不上VSYNC的信號而出現(xiàn)掉幀的情況。

      Profile GPU Rendering可以找到渲染有問題的界面,但是想要修復(fù)的話,只依賴Profile GPU Rendering是不夠的,可以用另一個工具Hierarchy Viewer來查看布局層次和每個View所花的時間,這個工具會在下一篇文章進行介紹。

      3.Systrace

      Systrace是Android4.1中新增的性能數(shù)據(jù)采樣和分析工具。它可幫助開發(fā)者收集Android關(guān)鍵子系統(tǒng)(SurfaceFlinger、WindowManagerService等Framework部分關(guān)鍵模塊、服務(wù),View體系系統(tǒng)等)的運行信息。Systrace的功能包括跟蹤系統(tǒng)的I/O操作、內(nèi)核工作隊列、CPU負(fù)載以及Android各個子系統(tǒng)的運行狀況等。對于UI顯示性能,比如動畫播放不流暢、渲染卡頓等問題提供了分析數(shù)據(jù)。

      3.1 使用Systrace

      Systrace跟蹤的設(shè)備要在Android4.1版本以上,對于Android4.3版本之前和4.3版本之后使用上有點區(qū)別,現(xiàn)在也很少有人用Android4.3之前的版本,因此這里只講Android4.3版本的使用方法。Systrace可以在DDMS上使用,可以使用命令行來使用,也可以在代碼中進行跟蹤。接下來分別來介紹這三種方式。
      在DDMS中使用Systrace
      1.首先我們要打開Android Studio的Tool中的Android Device Monitor,并連接手機。
      2.點擊Systrace按鈕進入抓取設(shè)置界面,如下圖所示。


      抓取設(shè)置界面可以設(shè)置跟蹤的時間,以及trace文件輸出的地址等內(nèi)容。如下圖所示。
      QQ截圖20170311224620_副本.pngQQ截圖20170311224620_副本.png

      3.設(shè)置完成后,我們就來操作的跟蹤的過程。跟蹤時間結(jié)束后,生成trace.html文件。
      4.用Chrome打開trace.html文件進行分析。分析的方法,后文會講到。

      用命令行使用Systrace
      Android 提供一個python腳本文件 systrace.py,它位于Android SDK 目錄 /tools/systrace 中,我們可以執(zhí)行以下命令來使用Systrace:

      $ cd android-sdk/platform-tools/systrace
      $ python systrace.py --time=10 -o newtrace.html sched gfx view wm
      

      在代碼中使用Systrace
      Systrace并不會追蹤應(yīng)用的所有工作,在Android4.3及以上版本的代碼中,可以使用Trace類對應(yīng)用中的具體活動進行追蹤。
      Android源碼中也引用了Trace類,比如RecyclerView:

      ...
       private final Runnable mUpdateChildViewsRunnable = new Runnable() {
              public void run() {
                  if (!mFirstLayoutComplete) {
                      return;
                  }
                  if (mDataSetHasChangedAfterLayout) {
                      TraceCompat.beginSection(TRACE_ON_DATA_SET_CHANGE_LAYOUT_TAG);
                      dispatchLayout();
                      TraceCompat.endSection();
                  } else if (mAdapterHelper.hasPendingUpdates()) {
                      TraceCompat.beginSection(TRACE_HANDLE_ADAPTER_UPDATES_TAG);
                      eatRequestLayout();
                      mAdapterHelper.preProcess();
                      if (!mLayoutRequestEaten) {
                          rebindUpdatedViewHolders();
                      }
                      resumeRequestLayout(true);
                      TraceCompat.endSection();
                  }
              }
          };
          ...
      View Code

      TraceCompat類對Trace類進行了封裝,只會在Android4.3及以上版本才會使用Trace類,其中beginSection方法和endSection方法之間的代碼會被追蹤,endSection方法會只會結(jié)束最近的beginSection方法,因此要保證beginSection方法和endSection方法的調(diào)用次數(shù)要相同。

      3.2 用Chrome分析Systrace

      通過前面的方法生成的trace.html需要用Chrome打開,打開后效果如下圖所示。

      我們可以使用W鍵和S鍵進行放大和縮小,A鍵和D鍵進行左右移動。
      Alert區(qū)域
      首先來看Alert區(qū)域,這一區(qū)域會標(biāo)記處性能有問題的點,單擊嘆號圖標(biāo)就可以查看某一個Alert的問題描述,如下所示。

      這個Alert指出了View在Measure/Layout時耗費了大量的時間,導(dǎo)致出現(xiàn)jank(同一幀畫了多次)。給出的建議是避免在動畫播放期間控制布局。

      CPU區(qū)域
      接下來我們來查看CPU區(qū)域,每一行代表一個CPU核心和它執(zhí)行任務(wù)的時間片,放大后會看到每個色塊代表一個執(zhí)行的進程,色塊的長度代表其執(zhí)行時間,如下圖所示。

      圖中CPU 0主要執(zhí)行adbb線程和InputReader線程,CPU 2主要執(zhí)行了surfaceflinger線程和ordinatorlayout進程中的RenderThread線程,我們點擊RenderThread色塊,會給出RenderThread的相關(guān)信息,如下圖所示。

      圖中給出了當(dāng)前色塊所運行的線程和進程、開啟時間和持續(xù)時間等信息。

      應(yīng)用區(qū)域
      應(yīng)用區(qū)域會顯示應(yīng)用的幀數(shù),如下圖所示。

      Systrace會給出應(yīng)用中的Frames分析,每一幀就是一個F圓圈,F(xiàn)圓圈有三種顏色,其中綠色表示Frame渲染流暢,黃色和紅色則代表渲染時間超過了16.6ms,其中紅的更嚴(yán)重些。我們點擊紅色F圓圈,會給出該Frame的信息,如下圖所示。

      從圖中可以看出,F(xiàn)rame給出了問題提示:Scheduling delay(調(diào)度延遲),當(dāng)一幀繪制時間超過19ms會觸發(fā)該提示,更何況這一幀已經(jīng)有將近40ms了。導(dǎo)致這一問題產(chǎn)生的原因主要是線程在繪制時,在很長一段時間都沒有分配到CPU時間片,因此無法繼續(xù)進行繪制。按m鍵來高亮該時間段,我們來查看CPU的情況,如下圖所示。

      可以看出這個時間段中兩個CPU都在滿負(fù)荷運行。至于具體是什么讓CPU繁忙,則需要使用Traceview來進行分析。

      Alerts總體分析
      點開最右邊的Alerts按鈕會給出Alert的總體分析,如下圖所示。
      QQ截圖20170312150637.pngQQ截圖20170312150637.png

      Alerts會給出Alert類型,以及出現(xiàn)的次數(shù)。有了這些總體的分析,方便開發(fā)者對該時間段的繪制性能有一個整體的大概了解,便于進行下一步分析。
      由于Systrace 是以系統(tǒng)的角度返回一些信息,只能為我們提供一個概覽,它的深度是有限的,我們可以用它來進行粗略的檢查,以便了解大概的情況,但是如果要分析更詳細(xì)的,比如要找到是什么讓CPU繁忙,某些方法的調(diào)用次數(shù)等,則還要借助另一個工具:Traceview。

      4.Traceview

      TraceView是Android SDK中自帶的數(shù)據(jù)采集和分析工具。一般來說,通過TraceView我們可以得到以下兩種數(shù)據(jù):

      • 單次執(zhí)行耗時的方法。
      • 執(zhí)行次數(shù)多的方法。

      4.1 使用Traceview

      要分析Traceview,則首先要得到一個trace文件,trace文件的獲取有兩種方式,分別是在DDMS中使用和在代碼中加入調(diào)試語句,下面分別對這兩種方式進行介紹。

      DDMS中使用
      1.首先我們要打開Android Studio的Tool中的Android Device Monitor,并連接手機。
      2.選擇相應(yīng)的進程,并單擊Start Method Profiling按鈕。
      3.對應(yīng)用中需要監(jiān)控的點進行操作。
      4.單擊Stop Method Profiling按鈕,會自動跳到TraceView視圖。

      代碼中加入調(diào)試語句
      如果開發(fā)中出現(xiàn)不好復(fù)現(xiàn)的問題,則需要在代碼中添加TraceView監(jiān)控語句,代碼如下所示。

      Debug.startMethodTracing();
      ...
      Debug.stopMethodTracing();
      View Code

      在開始監(jiān)控的地方調(diào)用startMethodTracing方法,在需要結(jié)束監(jiān)控的地方調(diào)用stopMethodTracing方法。系統(tǒng)會在SD卡中生成trace文件,將trace文件導(dǎo)出并用SDK中的Traceview打開即可。當(dāng)然不要忘了在manifest中加入 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>權(quán)限。

      4.2 分析Traceview

      為了分析Traceview,我們來舉一個簡單的例子來生成trace文件,這里采用第二種方式:代碼中加入調(diào)試語句。代碼如下所示。

      public class CoordinatorLayoutActivity extends AppCompatActivity {
          private ViewPager mViewPager;
          private TabLayout mTabLayout;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_tab_layout);
              Debug.startMethodTracing("test");//1
              initView();
         ...
          }
          private void initView() {
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
          @Override
          protected void onStop() {
              super.onStop();
              Debug.stopMethodTracing();
          }
      }
      View Code

      在注釋1處調(diào)用了startMethodTracing方法開始監(jiān)控,其中test是生成的trace文件的名稱。在initView中我們特意調(diào)用sleep方法來做耗時操作。在onStop方法中我們調(diào)用了stopMethodTracing方法結(jié)束監(jiān)控。這時會在SD卡根目錄生成test.trace文件,我們將該文件導(dǎo)出到桌面,用Traceview來分析test.trace文件,我們在cmd中執(zhí)行如下語句。

      我們進入traceview所在的目錄(直接將traceview.bat拖入到cmd中),并執(zhí)行上圖的traceview語句后會彈出Traceview視圖,它分為兩部分,分別是時間片面板和分析面板,我們先來看時間片面板,如下圖所示。


      其中x軸代表時間的消耗,單位為ms,y軸代表各個線程。一般會查看色塊的長度,明顯比較長的方法重點去關(guān)注,具體的分析還得看分析面板,如下圖所示。

      每一列數(shù)據(jù)的代表的含義如下表所示。

      列名含義
      Name 該線程運行過程中調(diào)用的函數(shù)名
      Incl Cpu Time% 某個方法包括其內(nèi)部調(diào)用的方法所占用CPU時間百分比
      Excl Cpu Time% 某個方法不包括其內(nèi)部調(diào)用的方法所占用CPU時間百分比
      Incl Real Time% 某個方法包括其內(nèi)部調(diào)用的方法所占用真實時間百分比
      Excl Real Time% 某個方法不包括其內(nèi)部調(diào)用的方法所占用真實時間百分比
      Calls + Recur Calls / Total 某個方法次數(shù)+遞歸調(diào)用次數(shù)
      Cpu Time / Call 該方法平均占用CPU時間
      Cpu Time / Call 該方法平均占用真實時間
      Incl Cpu Time 某個方法包括其內(nèi)部調(diào)用的方法所占用CPU時間
      Excl Cpu Time 某個方法不包括其內(nèi)部調(diào)用的方法所占用CPU時間
      Incl Real Time 某個方法包括其內(nèi)部調(diào)用的方法所占用真實時間
      Excl Real Time 某個方法不包括其內(nèi)部調(diào)用的方法所占用真實時間

      因為我們用sleep方法來進行耗時操作,所以這里我們可以單擊Incl Real Time來進行降序排列。其中有很多系統(tǒng)調(diào)用的方法,我們來進行一一過濾。最終我們發(fā)現(xiàn)了CoordinatorLayoutActivity的initView方法Incl Real Time的時間為1000.493ms,這顯然有問題,如下圖所示。

      從圖中我們可以看出是調(diào)用sleep方法導(dǎo)致的耗時。關(guān)于Traceview還有很多種分析情況,就需要大家在平時進行積累了。
      好了關(guān)于繪制性能分析,就講到這,如果覺得不過癮,本系列的后續(xù)文章還有大波的內(nèi)容會持續(xù)向你砸來。

        

      posted on 2018-07-16 09:30  安卓筆記俠  閱讀(1817)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 久久涩综合一区二区三区| 无码人妻久久久一区二区三区| 欧美国产日韩久久mv| 少妇激情一区二区三区视频小说| 国内精品自线在拍| 天堂国产一区二区三区| 国内熟妇人妻色在线视频| 亚洲一区二区三区在线观看精品中文| 亚洲第一成人网站| 日韩乱码人妻无码系列中文字幕 | 久久久久久免费一区二区三区| 亚洲午夜爱爱香蕉片| 手机看片福利一区二区三区| 久久综合九色综合欧洲98| 沿河| 色五月丁香五月综合五月| 在线国产精品中文字幕| 一区二区三区无码高清视频| 国产自拍一区二区三区在线| 午夜毛片不卡免费观看视频| 免费观看添你到高潮视频| 国产亚洲无线码一区二区| 亚洲欧美综合在线天堂| 日韩少妇人妻vs中文字幕| 丁香婷婷综合激情五月色| 人妻少妇精品性色av蜜桃| 亚洲嫩模喷白浆在线观看| 韩国精品一区二区三区在线观看 | 日韩在线视频一区二区三区| 精品国内自产拍在线观看| 色爱综合激情五月激情| 欧美成人aaa片一区国产精品| 日韩最新中文字幕| 四川丰满少妇无套内谢| 亚洲精品综合第一国产综合| 久久精品国产久精国产69| 色欲综合久久中文字幕网| 亚洲欧美日本久久网站| 欧美肥老太交视频免费 | 国产成人精品久久性色av| 好男人好资源WWW社区|