iOS離屏渲染之優(yōu)化分析

在進行iOS的應(yīng)用開發(fā)過程中,有時候會出現(xiàn)卡頓的問題,雖然iOS設(shè)備的性能越來越高,但是卡頓的問題還是有可能會出現(xiàn),而離屏渲染是造成卡頓的原因之一。因此,本文主要分析一下離屏渲染產(chǎn)生的原因及避免的方法,最后介紹一下Xcode自帶的分析離屏渲染的工具Instruments的使用。

UIView和CALayer關(guān)系

UIView繼承自UIResponder,可以處理系統(tǒng)傳遞過來的事件,如:UIApplication、UIViewController、UIView,以及所有從UIView派生出來的UIKit類。每個UIView內(nèi)部都有一個CALayer提供內(nèi)容的繪制和顯示,并且作為內(nèi)部RootLayer的代理視圖。

CALayer繼承自NSObject類,負責顯示UIView提供的內(nèi)容contents。CALayer有三個視覺元素:背景色、內(nèi)容和邊框,其中,內(nèi)容的本質(zhì)是一個CGImage

下圖為CALayer的結(jié)構(gòu)圖:

圖1

界面渲染過程

RunLoop有一個60fps的回調(diào),即每16.7ms繪制一次屏幕,所以view的繪制必須在這個時間內(nèi)完成,view內(nèi)容的繪制是CPU的工作,然后把繪制的內(nèi)容交給GPU渲染,包括多個View的拼接(Compositing)、紋理的渲染(Texture)等等,最后顯示在屏幕上。但是,如果無法是16.7ms內(nèi)完成繪制,就會出現(xiàn)丟幀的問題,一般情況下,如果幀率保證在30fps以上,界面卡頓效果不明顯,那么就需要在33.4ms內(nèi)完成View的繪制,而低于這個幀率,就會產(chǎn)生卡頓的效果,影響體驗。

渲染的過程如下:

  • UIViewlayer層有一個content,指向一塊緩存,即backing store
  • UIView繪制時,會調(diào)用drawRect方法,通過context將數(shù)據(jù)寫入backing store
  • backing store寫完后,通過render server交給GPU去渲染,將backing store中的bitmap數(shù)據(jù)顯示在屏幕上
圖2

離屏渲染

在使用圓角、陰影和遮罩等視圖功能的時候,圖層屬性的混合體被指定為在未預(yù)合成之前不能直接在屏幕中繪制,所有就需要在屏幕外的上下文中渲染,即離屏渲染。

離屏渲染卡頓原因

離屏渲染之所以會特別消耗性能,是因為要創(chuàng)建一個屏幕外的緩沖區(qū),然后從當屏緩沖區(qū)切換到屏幕外的緩沖區(qū),然后再完成渲染;其中,創(chuàng)建緩沖區(qū)和切換上下文最消耗性能,而繪制其實不是性能損耗的主要原因。

設(shè)置了以下屬性時,就會觸發(fā)離屏繪制:

  • shouldRasterize(光柵化)
  • masks(遮罩)
  • shadows(陰影)
  • edge antialiasing(抗鋸齒)
  • group opacity(不透明)
  • 復(fù)雜形狀設(shè)置圓角等
  • 漸變

屏幕渲染類型

CPU計算好顯示內(nèi)容提交到GPUGPU渲染完成后將渲染結(jié)果放入幀緩沖區(qū),隨后視頻控制器會按照 VSync信號逐行讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。

屏幕渲染有如下三種:

GPU中的屏幕渲染:

1、On-Screen Rendering

意為當前屏幕渲染,指的是GPU的渲染操作是在當前用于顯示的屏幕緩沖區(qū)中進行

2、Off-Screen Rendering

意為離屏渲染,指的是GPU在當前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進行渲染操作

3、CPU中的離屏渲染(特殊離屏渲染,即不在GPU中的渲染)

如果我們重寫了drawRect方法,并且使用任何Core Graphics的技術(shù)進行了繪制操作,就涉及到了CPU渲染

CoreGraphic通常是線程安全的,所以可以進行異步繪制,顯示的時候再放回主線程

切圓角優(yōu)化

切圓角是開發(fā)app過程中經(jīng)常會用到的功能,但是使用不同的方式,性能損耗也會不同,下面會介紹3種切圓角的方法;其中,方法三的性能相對最好。

方法一

使用cornerRadius進行切圓角,在iOS9之前會產(chǎn)生離屏渲染,比較消耗性能,而之后系統(tǒng)做了優(yōu)化,則不會產(chǎn)生離屏渲染,但是操作最簡單

iv.layer.cornerRadius = 30;
iv.layer.masksToBounds = YES;

方法二

利用mask設(shè)置圓角,利用的是UIBezierPathCAShapeLayer來完成

CAShapeLayer *mask1 = [[CAShapeLayer alloc] init];
mask1.opacity = 0.5;
mask1.path = [UIBezierPath bezierPathWithOvalInRect:iv.bounds].CGPath;
iv.layer.mask = mask1;

方法三

利用CoreGraphics畫一個圓形上下文,然后把圖片繪制上去,得到一個圓形的圖片,達到切圓角的目的。

- (UIImage *)drawCircleImage:(UIImage*)image
{
    CGFloat side = MIN(image.size.width, image.size.height);
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(side, side), false, [UIScreen mainScreen].scale);
    CGContextAddPath(UIGraphicsGetCurrentContext(), [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, side, side)].CGPath);
    CGContextClip(UIGraphicsGetCurrentContext());
    
    CGFloat marginX = -(image.size.width - side) * 0.5;
    CGFloat marginY = -(image.size.height - side) * 0.5;
    [image drawInRect:CGRectMake(marginX, marginY, image.size.width, image.size.height)];
    
    CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

Instruments使用

iOS的性能調(diào)試有許多方法,而官方提供的Instruments是一個強大的性能調(diào)試工具,可以分析如下功能:內(nèi)存、核心動畫、自動化、布局、網(wǎng)絡(luò)等等,本文主要介紹一下利用Core Animation來分析應(yīng)用的性能問題。

圖3

下面介紹一下Core Animation中的Debug屬性的部分功能,這些功能在分析離屏渲染等性能問題時十分有用:

Color Blended Layers

這個選項基于渲染程度對屏幕中的混合區(qū)域進行綠到紅的高亮(也就是多個半透明圖層的疊加)。由于重繪的原因,混合對GPU性能會有影響,同時也是滑動或者動畫幀率下降的罪魁禍首之一

Color Hits Green and Misses Red

當設(shè)置shouldRasterizep屬性為YES的時候,耗時的圖層繪制會被緩存,然后當做一個簡單的扁平圖片呈現(xiàn)。當緩存再生的時候這個選項就用紅色對柵格化圖層進行了高亮。如果緩存頻繁再生的話,就意味著柵格化可能會有負面的性能影響了

Color Offscreen-Rendered Yellow

開啟后會把那些需要離屏渲染的圖層高亮成黃色,這就意味著黃色圖層可能存在性能問題

當然Debug還有其它的選項,來分析不同的性能問題,如有需求,請參考其它資料。


iOS離屏渲染的性能分析到此結(jié)束,文中如有不足之處,歡迎指出,共同進步。(文中部分圖片來自互聯(lián)網(wǎng),版權(quán)歸原作者所有)

參考資料

iOS 離屏渲染的研究

iOS離屏渲染優(yōu)化(附DEMO)

iOS圖片設(shè)置圓角性能優(yōu)化

iOS --- UIView與CALayer的聯(lián)系與區(qū)別

iOS開發(fā)之圖形渲染分析、離屏渲染、當前屏幕渲染、On-Screen Rendering、Off-Screen Rendering

iOS-Core-Animation之十二----性能調(diào)優(yōu)

The Relationship Between Layers and Views

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容