iOS app性能優(yōu)化

轉(zhuǎn)載:http://www.reibang.com/p/2a01e5e2141f

http://blog.csdn.net/lg767201403/article/details/50960909

這次我們來(lái)說(shuō)說(shuō)iOS app中滑動(dòng)的那些事迟几。iOS為了提高滑動(dòng)的流暢感柳弄,特意在滑動(dòng)的時(shí)候?qū)unloop模式切換到UITrackingRunLoopMode啊奄,在這個(gè)過(guò)程中專心做跟滑動(dòng)相關(guān)的工作,這也就是在滑動(dòng)過(guò)程中為什么nstimer無(wú)法工作的原因,因?yàn)閮蓚€(gè)沒(méi)在同一mode下面。但我們可能經(jīng)常會(huì)遇到滑動(dòng)不怎么流暢的情況抒蚜,比如在項(xiàng)目中碰到在滑動(dòng)tableview的時(shí)候不怎么順暢,感覺(jué)有點(diǎn)不爽耘戚,即便是在測(cè)試中表現(xiàn)最好的5s(touch之類的感受更直觀)嗡髓。

tableview 滑動(dòng)不流暢

那碰到這種情況該怎么處理,分析圖像動(dòng)畫(huà)性能主要用的是Core Animation這個(gè)組件收津,先簡(jiǎn)單介紹一下里面一些經(jīng)常用到的選項(xiàng):

Color Blended layers

標(biāo)示混合的圖層會(huì)為紅色,不透明的圖層為綠色饿这,通常我們希望綠色的區(qū)域越多越好浊伙。

Color Hits Green and Misses Red

假如我們?cè)O(shè)置viewlayer的shouldRasterize為YES,那些成功被緩存的layer會(huì)標(biāo)注為綠色长捧,反之為紅色嚣鄙,下面會(huì)有詳細(xì)介紹。

Color copied images

標(biāo)示那些被Core Animation拷貝的圖片串结。這主要是因?yàn)樵搱D片的色彩格式不能被GPU直接處理哑子,需要在CPU這邊做轉(zhuǎn)換,假如在主線層做這個(gè)操作對(duì)性能會(huì)有一定的影響肌割。

Color misaligned images

被縮放的圖片會(huì)被標(biāo)記為黃色,像素不對(duì)齊則會(huì)標(biāo)注為紫色卧蜓。

Color offscreen-rendered yellow

標(biāo)示哪些layer需要做離屏渲染(offscreen-render)。

簡(jiǎn)單介紹完Core Animation的一些東西之后我們回過(guò)頭來(lái)看看哪些問(wèn)題會(huì)影響到圖形的性能声功,下面這張圖摘自WWDC2014(Advanced Graphics and Animations for iOS Apps烦却,這上面的一些分享非常有技術(shù)性)

performance investigation mindset.png

當(dāng)你碰到性能問(wèn)題的時(shí)候宠叼,你可以思考一下:

是否受到CPU或者GPU的限制先巴?是否有不必要的CPU渲染?是否有太多的離屏渲染操作冒冬?是否有太多的圖層混合操作伸蚯?是否有奇怪的圖片格式或者尺寸?是否涉及到昂貴的view或者效果简烤?view的層次結(jié)構(gòu)是否合理剂邮?

那么哪些是你最該開(kāi)始考慮的方向呢?通常發(fā)生圖形性能問(wèn)題的時(shí)候横侦,比如列表滑動(dòng)不順暢挥萌、動(dòng)畫(huà)卡頓等,大部分都是由于Offscreen Rendering(離屏渲染)或者blending導(dǎo)致的枉侧,因?yàn)檫@在動(dòng)畫(huà)的每一幀都會(huì)涉及到引瀑。

offscreen-render

什么是offscreen-render?offscreen-render涉及的內(nèi)容比較多榨馁,有offscreen-render那就有onscreen render憨栽,onscreen render指的是GPU在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行渲染,相反offscreen-render就是不在當(dāng)前的屏幕緩存區(qū)翼虫,而在另外的緩沖區(qū)進(jìn)行渲染屑柔,offscreen-render有兩種形式:

CPU的offscreen-render

使用CPU來(lái)完成渲染操縱,通常在你使用:

drawRect (如果沒(méi)有自定義繪制的任務(wù)就不要在子類中寫(xiě)一個(gè)空的drawRect方法珍剑,因?yàn)橹灰獙?shí)現(xiàn)了該方法掸宛,就會(huì)為視圖分配一個(gè)寄宿圖,這個(gè)寄宿圖的像素尺寸等于視圖大小乘以 contentsScale的值招拙,造成資源浪費(fèi))

使用Core Graphics

上面的兩種情況使用的就是CPU離屏渲染唧瘾,首先分配一塊內(nèi)存翔曲,然后進(jìn)行渲染操作生成一份bitmap位圖,整個(gè)渲染過(guò)程會(huì)在你的應(yīng)用中同步的進(jìn)行劈愚,接著再將位圖打包發(fā)送到iOS里一個(gè)單獨(dú)的進(jìn)程--render server瞳遍,理想情況下,render server將內(nèi)容交給GPU直接顯示到屏幕上菌羽。

GPU的offscreen-render

使用GPU在當(dāng)前屏幕緩沖區(qū)以外開(kāi)辟一個(gè)新的緩沖區(qū)進(jìn)行繪制掠械,通常發(fā)生的情況有:

設(shè)置cornerRadius, masks, shadows,edge antialiasing等

設(shè)置layer.shouldRasterize = YES

渲染流程

offscreen-render對(duì)性能到底有什么影響?通常大家說(shuō)的離屏渲染指的是GPU這塊(當(dāng)然CPU這塊也會(huì)有影響注祖,也需要消耗一定的資源)猾蒂,比如修改了layer的陰影或者圓角,GPU需要做額外的渲染操作是晨。通常GPU在做渲染的時(shí)候是很快的肚菠,但是涉及到offscreen-render的時(shí)候情況就可能有些不同,因?yàn)樾枰~外開(kāi)辟一個(gè)新的緩沖區(qū)進(jìn)行渲染罩缴,然后繪制到當(dāng)前屏幕的過(guò)程需要做onscreen跟offscreen上下文之間的切換蚊逢,這個(gè)過(guò)程的消耗會(huì)比較昂貴,涉及到OpenGL的pipeline跟barrier箫章,而且offscreen-render在每一幀都會(huì)涉及到烙荷,因此處理不當(dāng)肯定會(huì)對(duì)性能產(chǎn)生一定的影響,所以可以的話盡量減少offscreen-render的圖層檬寂,查看哪些圖層需要離屏渲染可以用Instruments的Core Animation工具進(jìn)行檢測(cè)终抽,Color Offscreen-Rendered Yellow選項(xiàng)會(huì)將對(duì)應(yīng)的圖層標(biāo)記為黃色。

Blending

假如最上層的view是不透明的桶至,那直接使用這個(gè)view的對(duì)應(yīng)顏色之就可以昼伴,但如果view是透明的,在計(jì)算像素的顏色值時(shí)就需要計(jì)算它下面圖層镣屹,透明的視圖越多圃郊,計(jì)算量就越大,因此也會(huì)對(duì)圖形的性能產(chǎn)生一定的影響野瘦,所以可以的話也盡量減少透明圖層的數(shù)目描沟。

Demo

下面給出一個(gè)簡(jiǎn)單demo的優(yōu)化過(guò)程,這個(gè)demo里面涉及到的問(wèn)題是在實(shí)際項(xiàng)目中所碰到的鞭光,也就是最上面那張圖里列表滑動(dòng)不流暢情況---由陰影以及圓角導(dǎo)致的offscreen-render吏廉。

整個(gè)頁(yè)面就是一個(gè)簡(jiǎn)單的tableview,其中頭像為圓角惰许,一個(gè)label有陰影效果席覆,滑動(dòng)的時(shí)候在iPod上幀率只有可憐的28FPS。

Color Offscreen-Rendered Yellow

28FPS.png

其中黃色的區(qū)域就是離屏渲染的地方汹买,也就是含有圓角跟陰影的layer佩伤。

shadowPath

設(shè)置label的陰影效果可以通過(guò):

cell.sign.layer.shadowOffset= CGSizeMake(0,2);cell.sign.layer.shadowOpacity=0.5;cell.sign.layer.shadowColor= [UIColorblackColor].CGColor;

但是你可以發(fā)現(xiàn)這會(huì)導(dǎo)致離屏渲染聊倔,一個(gè)簡(jiǎn)單的不需要離屏渲染的方法就是制定陰影的路徑,也就是設(shè)置layer的shadowPath屬性生巡,通過(guò)instruments發(fā)現(xiàn)陰影的地方?jīng)]有黃色了耙蔑,幀率也提高到了40FPS:

cell.sign.layer.shadowPath = [UIBezierPath? bezierPathWithRect:cell.sign.bounds].CGPath;

設(shè)置shadowPath消除離屏渲染.png

rasterize

對(duì)于圓角這種類似導(dǎo)致的性能問(wèn)題,最簡(jiǎn)單的就是在列表中不要使用圓角孤荣,假如要使用圓角的話甸陌,一種最快提升性能的方式就是設(shè)置layer的shouldRasterize為YES:

cell.layer.shouldRasterize = YES;cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

雖然被Rasterize的圖層也會(huì)引起離屏渲染,如下圖所示盐股,整個(gè)cell都被標(biāo)示為黃色:

shouldRasterize.png

layer設(shè)置shouldRasterize=Y(jié)ES之后钱豁,會(huì)把被光柵化的圖層保存成位圖并緩存起來(lái),其中圓角或者陰影之類的效果也是直接保存到位圖當(dāng)中疯汁,當(dāng)需要渲染到屏幕上的時(shí)候只需要到緩存中去取對(duì)應(yīng)的位圖進(jìn)行顯示就行了牲尺,加快了整個(gè)渲染過(guò)程』衔茫可以通過(guò)勾選instruments core animation中的Color Hits Green and Misses Red選項(xiàng)來(lái)查看圖層是否被緩存了谤碳,如果圖層顯示為綠色則表示已經(jīng)被緩存起來(lái)了,也就是這個(gè)緩沖區(qū)的內(nèi)容被復(fù)用了霹肝,不用在去重新創(chuàng)建緩沖區(qū)估蹄,反之則是用紅色標(biāo)示。如下圖可以看到設(shè)置shouldRasterize之后沫换,cell都被標(biāo)示為綠色了,如果滑動(dòng)過(guò)程中發(fā)現(xiàn)都是紅色的證明就有問(wèn)題了:

cached.png

再看看現(xiàn)在滑動(dòng)的幀率:

優(yōu)化后.png

可以發(fā)現(xiàn)現(xiàn)在滾動(dòng)的性能大大提高了最铁,光柵化對(duì)于那些有很多子view嵌套在一起讯赏、view的層級(jí)復(fù)雜或者有很復(fù)雜特效效果的圖層有很明顯的提升,因?yàn)檫@些內(nèi)容都被緩存到位圖當(dāng)中了冷尉。但是使用光柵化需要注意一些內(nèi)容:

適用于內(nèi)容基本不變的圖層

假如圖層的內(nèi)容經(jīng)常變化漱挎,比如cell里面有涉及到動(dòng)畫(huà)之類的,那么緩存的內(nèi)容就無(wú)效了雀哨,GPU需要重新創(chuàng)建緩存區(qū)磕谅,導(dǎo)致離屏渲染,這又涉及到OpenGL的上下文環(huán)境切換雾棺,反而降低性能膊夹。

不要過(guò)度使用

緩存區(qū)的大小被設(shè)置為屏幕大小的2.5倍,假如過(guò)分使用同樣會(huì)導(dǎo)致大量的離屏渲染捌浩。

如果緩存的內(nèi)容超過(guò)100ms沒(méi)有被使用則會(huì)被回收放刨。

tips

對(duì)于圓角可以使用一張中間圓形透明的圖覆蓋在上面,雖然這會(huì)引入blending操作尸饺,但是大部分情況下性能會(huì)比離屏渲染好进统。

讓你的view層次結(jié)構(gòu)平坦一些助币,因?yàn)镺penGL在渲染layer的時(shí)候,在碰到有子層級(jí)layer的時(shí)候可能需要停下來(lái)把兩者合成到一個(gè)buffer里再接著渲染螟碎。(When the OpenGL renderer goes to draw each layer, it may have to stop for some subhierarchies and composite them into a single buffer).

延遲加載圖片

有時(shí)候在邊滾動(dòng)邊設(shè)置圖片的時(shí)候可能會(huì)有一定的影響眉菱,因此可以在滾動(dòng)的時(shí)候imageview不執(zhí)行setimage的操作,滾動(dòng)停止的時(shí)候才加載圖片掉分,由于滾動(dòng)的時(shí)候NSRunloop是處于UITrackingRunLoopMode模式下倍谜,可以采用如下的方式,將設(shè)置圖片放到NSDefaultRunLoopMode模式下才進(jìn)行:

UIImage*downloadedImage = ...;? [self.avatarImageView performSelector:@selector(setImage:)? ? ? ? ? ? ? ? ? ? ? ? ? ? withObject:downloadedImage? ? ? ? ? ? ? ? ? ? ? ? ? ? afterDelay:0inModes:@[NSDefaultRunLoopMode]];

圖片加載的極限優(yōu)化方式:FastImageCache

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叉抡,一起剝皮案震驚了整個(gè)濱河市尔崔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌褥民,老刑警劉巖季春,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異消返,居然都是意外死亡载弄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門撵颊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宇攻,“玉大人,你說(shuō)我怎么就攤上這事倡勇〕阉ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵妻熊,是天一觀的道長(zhǎng)夸浅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)扔役,這世上最難降的妖魔是什么帆喇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮亿胸,結(jié)果婚禮上坯钦,老公的妹妹穿的比我還像新娘。我一直安慰自己侈玄,他們只是感情好婉刀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著拗馒,像睡著了一般路星。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天洋丐,我揣著相機(jī)與錄音呈昔,去河邊找鬼。 笑死友绝,一個(gè)胖子當(dāng)著我的面吹牛堤尾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迁客,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼郭宝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了掷漱?” 一聲冷哼從身側(cè)響起粘室,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卜范,沒(méi)想到半個(gè)月后衔统,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡海雪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年锦爵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奥裸。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡险掀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出湾宙,到底是詐尸還是另有隱情樟氢,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布创倔,位于F島的核電站嗡害,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏畦攘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一十电、第九天 我趴在偏房一處隱蔽的房頂上張望知押。 院中可真熱鬧,春花似錦鹃骂、人聲如沸台盯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)静盅。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒿叠,已是汗流浹背明垢。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留市咽,地道東北人痊银。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像施绎,于是被迫代替她去往敵國(guó)和親溯革。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容