Instruments之Core Animation學習

一,前言  

  當App發展到必定的規模,性能優化就成爲必不可少的一點。可是不少人,又對性能優化很陌生,畢竟日常大多時間都在寫業務邏輯,不多關注這個。最近在優化本身的項目,也收集了不少資料,這裏先淺談一下使用Instruments中CoreAnimation優化收穫的經驗以及總結,這是第一篇,後續會更新Timer Profiler,Leaks等其餘優化工具的具體用法。緩存

二,準備工做性能優化

    在性能優化中一個最具參考價值的屬性是FPS:全稱Frames Per Second,其實就是屏幕刷新率,蘋果的iphone推薦的刷新率是60Hz,也就是說GPU每秒鐘刷新屏幕60次,這每刷新一次就是一幀frame,FPS也就是每秒鐘刷新多少幀畫面。靜止不變的頁面FPS值是0,這個值是沒有參考意義的,只有當頁面在執行動畫或者滑動的時候,FPS值才具備參考價值,FPS值的大小體現了頁面的流暢程度高低,當低於45的時候卡頓會比較明顯。
 
注意點:

(1)使用真機調試。
(2)最好使用release包測試(release是發佈版本,蘋果會在release包中作不少優化工做,所以用release包測試出來的性能纔是最真實的)。

  啓動程序點擊XCode選擇左上角-XCode->Open Developer Tool ->Instruments,打開Instruments再選擇CoreAnimation:iphone

1437388-26a8f05f2f245b76.png

打開CoreAnimation工具

1437388-a68016e1b0e8747c.png

CoreAnimation調試界面性能

圖中1是FPS值。
圖中2是不一樣緯度的調試選項(下面會逐個介紹)。測試

  • Color Blended Layers (圖層混合)

這個選項是檢測哪裏發生了圖層混合,先介紹一下什麼是圖層混合?不少狀況下,界面都是會出現多個UI控件疊加的狀況,若是有透明或者半透明的控件,那麼GPU會去計算這些這些layer最終的顯示的顏色,也就是咱們肉眼所看到的效果。例如一個上層Veiw顏色是綠色RGB(0,255,0),下層又放了一個View顏色是紅色RGB(0,0,255),透明度是50%,那麼最終顯示到咱們眼前的顏色是藍色RGB(0,127.5,127.5)。這個計算過程會消耗必定的GPU資源損耗性能。若是咱們把上層的綠色View改成不透明, 那麼GPU就不用耗費資源計算,直接顯示綠色。混合顏色計算公式:優化

R(C)=alpha*R(B)+(1-alpha)*R(A)    R(x)、G(x)、B(x)分別指顏色x的RGB份量

若是出現圖層混合了,打開Color Blended Layers選項,那塊區域會顯示紅色,因此咱們調試的目的就是將紅色區域消減的越少越好。那麼如何減小紅色區域的出現呢?只要設置控件不透明便可。
(1)設置opaque 屬性爲true。
(2)給View設置一個不透明的顏色,沒有特殊須要設置白色便可。
若是你在lldb中po打印某個控件,你會發現打印出來的數據中,控件的opaque都是true,由於控件這個屬性的默認值都是true,因此第一種方法能夠直接忽略掉。使用第二種方法你會發現以前紅色的都消除掉了。動畫

1437388-ec967da78a905425.png

設置不透明以前spa

1437388-46c7b6d652799c13.png

設置不透明以後3d

label.backgroundColor = [UIColor whiteColor];
label.layer.masksToBounds = YES;

  到這裏你可能奇怪,設置label的背景色第一行不就夠了麼,爲何還有第二行?這是由於若是label的內容是中文,label實際渲染區域要大於label的size,最外層多了一個sublayer,若是不設置第二行label的邊緣外層灰出現圖層混合的紅色,所以須要在label內容是中文的狀況下加第二句。單獨使用label.layer.masksToBounds = YES是不會發生離屏渲染,下文會講離屏渲染。
注意點:UIImageView控件比較特殊,不只須要自身這個容器是不透明的,而且imageView包含的內容圖片也必須是不透明的,若是你本身的圖片出現了圖層混合紅色,先檢查是否是本身的代碼有問題,若是確認代碼沒問題,就是圖片自身的問題,能夠聯繫大家的UI眉眉~

 

Color Hits Green and Misses Red(光柵化)

  這個選項主要是檢測咱們是是否正確使用layer的shouldRasterize屬性,shouldRasterize = YES開啓光柵化。什麼是光柵化?光柵化是將一個layer預先渲染成位圖(bitmap),再加入到緩存中,成功被緩存的layer會標註爲綠色,沒有成功緩存的會標註爲紅色,正確使用光柵化能夠獲得必定程度的性能提高。
適用狀況:通常在圖像內容不變的狀況下才使用光柵化,例如設置陰影耗費資源比較多的靜態內容,若是使用光柵化對性能的提高有必定幫助。
  非適用狀況:若是內容會常常變更,這個時候不要開啓,不然會形成性能的浪費。例如咱們在使用tableViewCell中,通常不要用光柵化,由於tableViewCell的繪製很是頻繁,內容在不斷的變化,若是使用了光柵化,會形成大量的離屏渲染下降性能。
若是你在一個界面中使用了光柵化,剛進去這個頁面的全部使用了光柵化的控件layer都會是紅色,由於尚未緩存成功,若是上下滑動你會發現,layer變成了綠色。可是若是你滑動幅度較大會發現,新出現的控件會是紅色而後變成綠色,由於剛開始這些控件的layer尚未緩存。
  注意點:
(1)系統給光柵化緩存分配了一個固定的大小,所以不能過分使用,若是超出了緩存也會形成離屏渲染。
(2)緩存的時間爲100ms,所以若是在100ms內沒有使用緩存的對象,則會從緩存中清除。

01.png

 

Color Copied Images(圖片顏色格式)

  Shows images that are copied by Core Animation in blue蘋果官方註釋被拷貝給CPU進行轉化的圖片顯示爲綠色。那麼這句話怎麼理解呢?若是GPU不支持當前圖片的顏色格式,那麼就會將圖片交給CPU預先進行格式轉化,而且這張圖片標記爲藍色。那麼GPU支持什麼格式呢?蘋果的GPU只解析32bit的顏色格式,若是使用Color Copied Images去調試發現是藍色,這個時候你也能夠去找大家的UI眉眉了~
  知識擴展:32bit指的是圖片顏色深度,用「位」來表示,用來表示顯示顏色數量,例如一個圖片支持256種顏色,那麼就須要256個不一樣的值來表示不一樣的顏色,也就是從0到255,二進制表示就是從00000000到11111111,一共須要8位二進制數,因此顏色深度是8。一般32bit色彩中使用三個8bit分別表示R紅G綠B藍,還有一個8bit經常使用來表示透明度(Alpha)。

 

Color Non-Standard Surface Formats (不標準的表面顏色格式)

  這個調試選項沒有一篇博文講過,都是直接略過,我也嘗試不少途徑去找這個選項究竟是什麼做用,然而蘋果開發文檔以及stack overflow都沒有對這個有所解釋。本身真機調試嘗試了不少發現有個規律,就是打開這個選項,某些Label和Button的背景顏色都會出現銀白色,可是不是必先現的,有些Label和Button依然正常顏色背景。其餘ImageView等控件是不會出現銀白色的背景顏色,猜測是否是和文本Text的設置有關係。若是您對這個有所瞭解,歡迎討論。

02.png

Color Non-Standard Surface Formats調試效果

 

Color Immediately(顏色刷新頻率)

  當執行顏色刷新的時候移除10ms的延遲,由於可能在特定狀況下你不須要這些延遲,因此使用此選項加快顏色刷新的頻率。不過通常這個調試選項咱們是用不到的。

Color Misaligned Images(圖片大小)

  這個選項能夠幫助咱們查看圖片大小是否正確顯示。若是image size和imageView size不匹配,image會出現黃色。要儘量的減小黃色的出現,由於image size與imageView size不匹配,會消耗資源壓縮圖片。下圖中的image實際size(81,110),頂部image正常,底部image出現黃色由於放在了一個size x 2的imageView容器中。

03.png

Color Misaligned Images調試效果圖

 

Color Offscreen-Rendered Yellow(離屏渲染)

  離屏渲染Off-Screen Rendering 指的是GPU在當前屏幕緩衝區之外新開闢一個緩衝區進行渲染操做。還有另一種屏幕渲染方式-當前屏幕渲染On-Screen Rendering ,指的是GPU的渲染操做是在當前用於顯示的屏幕緩衝區中進行。 離屏渲染會先在屏幕外建立新緩衝區,離屏渲染結束後,再從離屏切到當前屏幕, 把離屏的渲染結果顯示到當前屏幕上,這個上下文切換的過程是很是消耗性能的,實際開發中儘量避免離屏渲染。
觸發離屏渲染Offscreen rendering的行爲:
(1)drawRect:方法
(2)layer.shadow
(3)layer.allowsGroupOpacity or layer.allowsEdgeAntialiasing
(4)layer.shouldRasterize
(5)layer.mask
(6)layer.masksToBounds && layer.cornerRadius
這裏有須要注意的是第三條layer.shouldRasterize ,其實就是咱們本文講的第三個選項光柵化,光柵化會觸發離屏渲染,所以光柵化慎用。
  第六條設置圓角會觸發離屏渲染,若是在某個頁面大量使用了圓角,會很是消耗性能形成FPS急劇降低,設置圓角觸發離屏渲染要同時知足下面兩個條件:

layer.masksToBounds = YES;
layer.cornerRadius = 5;

下圖是給一個label設置了圓角,觸發離屏渲染:

1437388-d2f26e7dc65df03e.png

離屏渲染效果圖.jpg

爲了儘量避免觸發離屏渲染,咱們能夠換其餘手段來實現必要的功能:
(1)陰影繪製shadow:使用ShadowPath來替代shadowOffset等屬性的設置
imageViewLayer.shadowPath = CGPathCreateWithRect(imageRect, NULL);
(2)利用GraphicsContex生成一張帶圓角的圖片或者view,這裏不寫具體實現過程,須要的能夠度娘Copy,不少現成的代碼。

 

Color Compositing Fast-Path Blue (快速路徑)

  Places a blue overlay over content that is detached from the compositor.標記由硬件繪製的路徑爲藍色,藍色越多越好,能夠對直接使用OpenGL繪製的圖層進行高亮。沒有對OpenGL有過多的研究,因此這裏沒辦法給出demo,你們只須要記住藍色越多越好就ok。

 

Flash Updated Regions (重繪區域)

  Colors regions on your iOS device in yellow when those regions are updated by the graphics processor.這個選項會對重繪的內容高亮成黃色,重繪就是指使用Core Graphics繪製,繪製會損耗必定的性能,所以重繪區域應該越小越好。下圖是用真機進入原生地圖開啓Flash Updated Regions 調試的效果圖,很惋惜截屏不能截到黃色的區域,所以我用紅框圈起來,一共兩處,坐上角的是在不停的刷新頁面,右下角是在不停的刷新當前位置,所以都是使用Core Graphics重繪刷新的一種場景,而且你能夠發現黃色區域很小,區域越小性能越好。

1437388-3ef210b05a8efaec.png

Flash Updated Regions開啓地圖效果圖

相關文章
相關標籤/搜索