偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

iOS進階之頁面性能優(yōu)化

移動開發(fā) iOS
在軟件開發(fā)領(lǐng)域里經(jīng)常能聽到這樣一句話,“過早的優(yōu)化是萬惡之源”,不要過早優(yōu)化或者過度優(yōu)化。我認為在編碼過程中時刻注意性能影響是有必要的,但凡事都有個度,不能為了性能耽誤了開發(fā)進度。在時間緊急的情況下我們往往采用“quick and dirty”的方案來快速出成果,后面再迭代優(yōu)化,即所謂的敏捷開發(fā)。與之相對應(yīng)的是傳統(tǒng)軟件開發(fā)中的瀑布流開發(fā)流程。

前言

在軟件開發(fā)領(lǐng)域里經(jīng)常能聽到這樣一句話,“過早的優(yōu)化是萬惡之源”,不要過早優(yōu)化或者過度優(yōu)化。我認為在編碼過程中時刻注意性能影響是有必要的,但凡事都有個度,不能為了性能耽誤了開發(fā)進度。在時間緊急的情況下我們往往采用“quick and dirty”的方案來快速出成果,后面再迭代優(yōu)化,即所謂的敏捷開發(fā)。與之相對應(yīng)的是傳統(tǒng)軟件開發(fā)中的瀑布流開發(fā)流程。

卡頓產(chǎn)生的原因 

 

 

卡頓產(chǎn)生的原因 

在 iOS 系統(tǒng)中,圖像內(nèi)容展示到屏幕的過程需要 CPU 和 GPU 共同參與。CPU 負責(zé)計算顯示內(nèi)容,比如視圖的創(chuàng)建、布局計算、圖片解碼、文本繪制等。隨后 CPU 會將計算好的內(nèi)容提交到 GPU 去,由 GPU 進行變換、合成、渲染。之后 GPU 會把渲染結(jié)果提交到幀緩沖區(qū)去,等待下一次 VSync 信號到來時顯示到屏幕上。由于垂直同步的機制,如果在一個 VSync 時間內(nèi),CPU 或者 GPU 沒有完成內(nèi)容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時顯示屏?xí)A糁暗膬?nèi)容不變。這就是界面卡頓的原因。

因此,我們需要平衡 CPU 和 GPU 的負荷避免一方超負荷運算。為了做到這一點,我們首先得了解 CPU 和 GPU 各自負責(zé)哪些內(nèi)容。 

 

 

 

上面的圖展示了 iOS 系統(tǒng)下各個模塊所處的位置,下面我們再具體看一下 CPU 和 GPU 對應(yīng)了哪些操作。

CPU 消耗型任務(wù)

布局計算

布局計算是 iOS 中最為常見的消耗 CPU 資源的地方,如果視圖層級關(guān)系比較復(fù)雜,計算出所有圖層的布局信息就會消耗一部分時間。因此我們應(yīng)該盡量提前計算好布局信息,然后在合適的時機調(diào)整對應(yīng)的屬性。還要避免不必要的更新,只在真正發(fā)生了布局改變時再更新。

對象創(chuàng)建

對象創(chuàng)建過程伴隨著內(nèi)存分配、屬性設(shè)置、甚至還有讀取文件等操作,比較消耗 CPU 資源。盡量用輕量的對象代替重量的對象,可以對性能有所優(yōu)化。比如 CALayer 比 UIView 要輕量許多,如果視圖元素不需要響應(yīng)觸摸事件,用 CALayer 會更加合適。

通過 Storyboard 創(chuàng)建視圖對象還會涉及到文件反序列化操作,其資源消耗會比直接通過代碼創(chuàng)建對象要大非常多,在性能敏感的界面里,Storyboard 并不是一個好的技術(shù)選擇。

對于列表類型的頁面,還可以參考 UITableView 的復(fù)用機制。每次要初始化 View 對象時先根據(jù) identifier 從緩存池里取,能取到就復(fù)用這個 View 對象,取不到再真正執(zhí)行初始化過程?;瑒悠聊粫r,會將滑出屏幕外的 View 對象根據(jù) identifier 放入緩存池,新進入屏幕可見范圍內(nèi)的 View 又根據(jù)前面的規(guī)則來決定是否要真正初始化。

Autolayout

Autolayout 是蘋果在 iOS6 之后新引入的布局技術(shù),在大多數(shù)情況下這一技術(shù)都能大大提升開發(fā)速度,特別是在需要處理多語言時。比如阿拉伯語下布局是從右往左,通過 Autolayout 設(shè)置 leading 和 trailing 即可。

但是 Autolayout 對于復(fù)雜視圖來說常常會產(chǎn)生嚴重的性能問題,對于性能敏感的頁面建議還是使用手動布局的方式,并控制好刷新頻率,做到真正需要調(diào)整布局時再重新布局。

文本計算

如果一個界面中包含大量文本(比如微博、微信朋友圈等),文本的寬高計算會占用很大一部分資源,并且不可避免。

一個比較常見的場景是在 UITableView 中,heightForRowAtIndexPath這個方法會被頻繁調(diào)用,即使不是耗時的計算在調(diào)用次數(shù)多了之后也會帶來性能損耗。這里的優(yōu)化就是盡量避免每次都重新進行文本的行高計算,可以在獲取到 Model 數(shù)據(jù)后就根據(jù)文本內(nèi)容計算好布局信息,然后將這份布局信息作為一個屬性保存到對應(yīng)的 Model 中,這樣在 UITableView 的回調(diào)中就可以直接使用 Model 中的屬性,減少了文本的計算。

文本渲染 

 

 

 

屏幕上能看到的所有文本內(nèi)容控件,包括 UIWebView,在底層都是通過 CoreText 排版、繪制為 Bitmap 顯示的。常見的文本控件 (UILabel、UITextView 等),其排版和繪制都是在主線程進行的,當(dāng)顯示大量文本時,CPU 的壓力會非常大。

這一部分的性能優(yōu)化就需要我們放棄使用系統(tǒng)提供的上層控件轉(zhuǎn)而直接使用 CoreText 進行排版控制。

Wherever possible, try to avoid making changes to the frame of a view that contains text, because it will cause the text to be redrawn. For example, if you need to display a static block of text in the corner of a layer that frequently changes size, put the text in a sublayer instead.

上面這段話引用自 iOS Core Animation: Advanced Techniques,翻譯過來的意思就是說包含文本的視圖在改變布局時會觸發(fā)文本的重新渲染,對于靜態(tài)文本我們應(yīng)該盡量減少它所在視圖的布局修改。

圖像的繪制

圖像的繪制通常是指用那些以 CG 開頭的方法把圖像繪制到畫布中,然后從畫布創(chuàng)建圖片并顯示的過程。前面的模塊圖里介紹了 CoreGraphic 是作用在 CPU 之上的,因此調(diào)用 CG 開頭的方法消耗的是 CPU 資源。我們可以將繪制過程放到后臺線程,然后在主線程里將結(jié)果設(shè)置到 layer 的 contents 中。代碼如下:

  1. - (void)display { 
  2.     dispatch_async(backgroundQueue, ^{ 
  3.         CGContextRef ctx = CGBitmapContextCreate(...); 
  4.         // draw in context... 
  5.         CGImageRef img = CGBitmapContextCreateImage(ctx); 
  6.         CFRelease(ctx); 
  7.         dispatch_async(mainQueue, ^{ 
  8.             layer.contents = img; 
  9.         }); 
  10.     }); 
  11.  

圖片的解碼

Once an image file has been loaded, it must then be decompressed. This decompression can be a computationally complex task and take considerable time. The decompressed image will also use substantially more memory than the original.

圖片被加載后需要解碼,圖片的解碼是一個復(fù)雜耗時的過程,并且需要占用比原始圖片還多的內(nèi)存資源。

為了節(jié)省內(nèi)存,iOS 系統(tǒng)會延遲解碼過程, 在圖片被設(shè)置到 layer 的 contents 屬性或者設(shè)置成 UIImageView 的 image 屬性后才會執(zhí)行解碼過程,但是這兩個操作都是在主線程進行,還是會帶來性能問題。

如果想要提前解碼,可以使用 ImageIO 或者提前將圖片繪制到 CGContext 中,這部分實踐可以參考 iOS Core Animation: Advanced Techniques

這里多提一點,常用的 UIImage 加載方法有 imageNamed 和 imageWithContentsOfFile。其中 imageNamed 加載圖片后會馬上解碼,并且系統(tǒng)會將解碼后的圖片緩存起來,但是這個緩存策略是不公開的,我們無法知道圖片什么時候會被釋放。因此在一些性能敏感的頁面,我們還可以用 static 變量 hold 住 imageNamed 加載到的圖片避免被釋放掉,以空間換時間的方式來提高性能。

GPU消耗型任務(wù)

相對于 CPU 來說,GPU 能干的事情比較單一:接收提交的紋理(Texture)和頂點描述(三角形),應(yīng)用變換(transform)、混合并渲染,然后輸出到屏幕上。寬泛的說,大多數(shù) CALayer 的屬性都是用 GPU 來繪制。

以下一些操作會降低 GPU 繪制的性能,

大量幾何結(jié)構(gòu)

所有的 Bitmap,包括圖片、文本、柵格化的內(nèi)容,最終都要由內(nèi)存提交到顯存,綁定為 GPU Texture。不論是提交到顯存的過程,還是 GPU 調(diào)整和渲染 Texture 的過程,都要消耗不少 GPU 資源。當(dāng)在較短時間顯示大量圖片時(比如 TableView 存在非常多的圖片并且快速滑動時),CPU 占用率很低,GPU 占用非常高,界面仍然會掉幀。避免這種情況的方法只能是盡量減少在短時間內(nèi)大量圖片的顯示,盡可能將多張圖片合成為一張進行顯示。

另外當(dāng)圖片過大,超過 GPU 的最大紋理尺寸時,圖片需要先由 CPU 進行預(yù)處理,這對 CPU 和 GPU 都會帶來額外的資源消耗。

視圖的混合

當(dāng)多個視圖(或者說 CALayer)重疊在一起顯示時,GPU 會首先把他們混合到一起。如果視圖結(jié)構(gòu)過于復(fù)雜,混合的過程也會消耗很多 GPU 資源。為了減輕這種情況的 GPU 消耗,應(yīng)用應(yīng)當(dāng)盡量減少視圖數(shù)量和層次,并且減少不必要的透明視圖。

離屏渲染

離屏渲染是指圖層在被顯示之前是在當(dāng)前屏幕緩沖區(qū)以外開辟的一個緩沖區(qū)進行渲染操作。

離屏渲染需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕,而上下文環(huán)境的切換是一項高開銷的動作。

會造成 offscreen rendering 的原因有:

  • 陰影(UIView.layer.shadowOffset/shadowRadius/…)
  • 圓角(當(dāng) UIView.layer.cornerRadius 和 UIView.layer.maskToBounds 一起使用時)
  • 圖層蒙板
  • 開啟光柵化(shouldRasterize = true)

使用陰影時同時設(shè)置 shadowPath 就能避免離屏渲染大大提升性能,后面會有一個 Demo 來演示;圓角觸發(fā)的離屏渲染可以用 CoreGraphics 將圖片處理成圓角來避免。

CALayer 有一個 shouldRasterize 屬性,將這個屬性設(shè)置成 true 后就開啟了光柵化。開啟光柵化后會將圖層繪制到一個屏幕外的圖像,然后這個圖像將會被緩存起來并繪制到實際圖層的 contents 和子圖層,對于有很多的子圖層或者有復(fù)雜的效果應(yīng)用,這樣做就會比重繪所有事務(wù)的所有幀來更加高效。但是光柵化原始圖像需要時間,而且會消耗額外的內(nèi)存。

光柵化也會帶來一定的性能損耗,是否要開啟就要根據(jù)實際的使用場景了,圖層內(nèi)容頻繁變化時不建議使用。最好還是用 Instruments 比對開啟前后的 FPS 來看是否起到了優(yōu)化效果。

注意:

shouldRasterize = true 時記得同時設(shè)置 rasterizationScale

Instruments 使用 

 

 

 

Instruments 是一系列工具集,我們這里只演示 Core Animation 的使用。在 Core Animation 選項右下方會看到如下選項, 

 

 

 

Color Blended Layers

這個選項選項基于渲染程度對屏幕中的混合區(qū)域進行綠到紅的高亮顯示,越紅表示性能越差,會對幀率等指標(biāo)造成較大的影響。紅色通常是由于多個半透明圖層疊加引起。

Color Hits Green and Misses Red

當(dāng) UIView.layer.shouldRasterize = YES 時,耗時的圖片繪制會被緩存,并當(dāng)做一個簡單的扁平圖片來呈現(xiàn)。這時候,如果頁面的其他區(qū)塊(比如 UITableViewCell 的復(fù)用)使用緩存直接命中,就顯示綠色,反之,如果不命中,這時就顯示紅色。紅色越多,性能越差。因為柵格化生成緩存的過程是有開銷的,如果緩存能被大量命中和有效使用,則總體上會降低開銷,反之則意味著要頻繁生成新的緩存,這會讓性能問題雪上加霜。

Color Copied Images

對于 GPU 不支持的色彩格式的圖片只能由 CPU 來處理,把這樣的圖片標(biāo)為藍色。藍色越多,性能越差。

Color Immediately

通常 Core Animation Instruments 以每毫秒 10 次的頻率更新圖層調(diào)試顏色。對某些效果來說,這顯然太慢了。這個選項就可以用來設(shè)置每幀都更新(可能會影響到渲染性能,而且會導(dǎo)致幀率測量不準,所以不要一直都設(shè)置它)。

Color Misaligned Images

這個選項檢查了圖片是否被縮放,以及像素是否對齊。被放縮的圖片會被標(biāo)記為黃色,像素不對齊則會標(biāo)注為紫色。黃色、紫色越多,性能越差。

Color Offscreen-Rendered Yellow

這個選項會把那些離屏渲染的圖層顯示為黃色。黃色越多,性能越差。這些顯示為黃色的圖層很可能需要用 shadowPath 或者 shouldRasterize 來優(yōu)化。

Color OpenGL Fast Path Blue

這個選項會把任何直接使用 OpenGL 繪制的圖層顯示為藍色。藍色越多,性能越好。如果僅僅使用 UIKit 或者 Core Animation 的 API,那么不會有任何效果。

Flash Updated Regions

這個選項會把重繪的內(nèi)容顯示為黃色。不該出現(xiàn)的黃色越多,性能越差。通常我們希望只是更新的部分被標(biāo)記完黃色。

演示

上述幾個選項中常用來檢測性能的是 Color Blended Layers、Offscreen-Rendered Yellow 和 Color Hits Green and Misses Red。下面我重點演示一下離屏渲染和光柵化的檢測,寫了一個簡單的 Demo 設(shè)置了陰影效果,代碼如下:

  1. view.layer.shadowOffset = CGSizeMake(1, 1); 
  2.     view.layer.shadowOpacity = 1.0; 
  3.     view.layer.shadowRadius = 2.0; 
  4.     view.layer.shadowColor = [UIColor blackColor].CGColor; 
  5. //    view.layer.shadowPath = CGPathCreateWithRect(CGRectMake(0, 0, 50, 50), NULL);  

shadowPath 沒有設(shè)置時用 Instruments 檢測 FPS 基本在 20 以下(iPhone6設(shè)備),設(shè)置了 shadowPath 后基本維持在 55 左右,性能提升十分明顯。

下面來看一下光柵化的檢測,代碼如下,

  1. view.layer.shouldRasterize = YES; 
  2. view.layer.rasterizationScale = [UIScreen mainScreen].scale;  

勾選 Color Hits Green and Misses Red 選項后顯示如下: 

 

 

 

我們可以看到在靜止時緩存都生效了,在快速滑動時緩存基本不起作用,因此是否要開啟光柵化還是得根據(jù)具體場景,用 Instruments 檢測開啟前后的性能來決定。

總結(jié)

本文主要總結(jié)了性能調(diào)優(yōu)的一些理論知識,后面還介紹了 Instruments 中 Core Animation 的一些性能檢測指標(biāo)用法。性能優(yōu)化最重要的是要使用工具來檢測而不是猜測,先查看是否有離屏渲染等問題,再用 Time Profiler 分析一下耗時的函數(shù)調(diào)用。修改后再用工具分析是否有改善,一步一步執(zhí)行,小心仔細。

建議大家也實際動手分析一下自己的應(yīng)用,加深一下印象,enjoy~

責(zé)任編輯:龐桂玉 來源: iOS大全
相關(guān)推薦

2013-01-22 15:27:23

WebWeb前端

2009-09-08 09:45:23

App Engine性

2013-12-17 16:21:17

iOSiOS性能優(yōu)化

2021-07-29 14:20:34

網(wǎng)絡(luò)優(yōu)化移動互聯(lián)網(wǎng)數(shù)據(jù)存儲

2021-11-29 11:13:45

服務(wù)器網(wǎng)絡(luò)性能

2022-02-16 14:10:51

服務(wù)器性能優(yōu)化Linux

2018-01-09 16:56:32

數(shù)據(jù)庫OracleSQL優(yōu)化

2019-12-13 10:25:08

Android性能優(yōu)化啟動優(yōu)化

2009-06-30 11:23:02

性能優(yōu)化

2025-01-20 09:09:59

2013-02-20 14:32:37

Android開發(fā)性能

2023-07-19 12:24:48

C++constexpr?語句

2011-07-11 15:26:49

性能優(yōu)化算法

2022-01-10 08:50:13

URL前端頁面

2016-08-12 10:23:28

javascriptChrome前端

2023-04-10 11:18:38

前端性能優(yōu)化

2011-06-14 11:14:10

性能優(yōu)化代碼

2011-06-14 14:17:23

性能優(yōu)化系統(tǒng)層次

2021-07-16 23:01:03

SQL索引性能

2013-09-17 10:32:08

Android性能優(yōu)化數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號