小心別讓圓角成了你列表的幀數(shù)殺手

[轉(zhuǎn)自] http://supermao.cn/xiao-xin-bie-rang-yuan-jiao-cheng-liao-ni-lie-biao-de-zheng-shu-sha-shou/#rd?sukey=3fed89b912c7bbb2afd9c1d1fe4dda38796f471b2f6205a4af2fccd04b26a7bdf186785bc36fa2ad554bd7b458a4de69
前言
在iOS的世界,圓角無處不在间影,而且必須存在凯正。因為圓角是符合人類視覺安全體驗的柱衔,圓角讓人覺得舒適姑隅,而方角在潛意識層次是具有傷害體驗的,因為尖尖的東西總是有可能對人造成傷害的南片,所以我們更喜歡圓角眼滤。在我之前的文章中講過,在iOS的中設(shè)置圓角是非常容易的一件事情大猛,這也體現(xiàn)出蘋果也是非常重視圓角這件事情的扭倾。
圓角雖好,但如果使用不當(dāng)挽绩,它就是你的幀數(shù)殺手膛壹,特別當(dāng)它出現(xiàn)在滾動列表的時候。下面來看圓角如何毀掉你的流暢度的。
實測
layer.cornerRadius
我創(chuàng)建了一個簡單地UITableView視圖模聋,為每個cell添加了2個UIImageView實例肩民,且為UIImageView實例進行如下設(shè)置
aImageView.layer.cornerRadius = aImageView.frame.size.width/2.0; aImageView.layer.masksToBounds = YES;

運行截圖如下:


image

你們猜,現(xiàn)在滾動的幀率是多少链方。


image

已經(jīng)跌至45幀每秒持痰,這個幀率已經(jīng)讓人感覺到不那么順滑了,如果低于40幀每秒祟蚀,普通用戶就會察覺明顯的不流暢了工窍。當(dāng)我把cell的UIImageView實例增加至四個
image

現(xiàn)在幀率已經(jīng)低于30幀每秒了


image

這個幀率如果出現(xiàn)在首屏,足以引領(lǐng)你的app進入垃圾級別的體驗了≡萏猓現(xiàn)在我把UIImageView實例的size調(diào)的小一些移剪。
image

平均幀率提高了大概3幀每秒。
image

在這里視圖和圓角的大小對幀率并沒有什么卵影響薪者,數(shù)量才是傷害的核心輸出啊纵苛。
layer.mask
之前有的文章說通過layer.cornerRadius和layer.mask設(shè)置圓角并沒有什么差異言津,事實真的是這樣的嗎攻人?我如下設(shè)置了圓角:

CAShapeLayer *layer = [CAShapeLayer layer]; UIBezierPath *aPath = [UIBezierPath bezierPathWithOvalInRect:aImageView.bounds]; layer.path = aPath.CGPath; aImageView.layer.mask = layer;

得到的幀率如下:


image

竟然只有20幀每秒了,比layer.cornerRadius還少了8幀;澄恰!初婆!所以layer.cornerRadius實現(xiàn)圓角的性能是要比layer.mask要高很多蓬坡。
maskView
iOS的UIView多了一個maskView方法屑咳,不過這個東西和layer.mask是一個卵樣的敲董。
原理
上面拖慢幀率的原因其實都是Off-Screen Rendering
(離屏渲染)的原因聪铺。離屏渲染是個好東西计寇,但是頻繁發(fā)生離屏渲染是非常耗時的赖阻。
Off-Screen Rendering
離屏渲染,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個緩沖區(qū)進行渲染操作。由上面的一個結(jié)論視圖和圓角的大小對幀率并沒有什么卵影響于未,數(shù)量才是傷害的核心輸出啊烘浦。
可以知道離屏渲染耗時是發(fā)生在離屏這個動作上面握侧,而不是渲染品擎。為什么離屏
這么耗時坦喘?原因主要有創(chuàng)建緩沖區(qū)
和上下文切換
。創(chuàng)建新的緩沖區(qū)代價都不算大梦碗,付出最大代價的是上下文切換。
上下文切換
上下文切換斩例,不管是在GPU渲染過程中础钠,還是一直所熟悉的進程切換,上下文切換在哪里都是一個相當(dāng)耗時的操作翻具。首先我要保存當(dāng)前屏幕渲染環(huán)境叹洲,然后切換到一個新的繪制環(huán)境民泵,申請繪制資源,初始化環(huán)境,然后開始一個繪制霞扬,繪制完畢后銷毀這個繪制環(huán)境萤彩,如需要切換到On-Screen Rendering或者再開始一個新的離屏渲染重復(fù)之前的操作。下圖描述了一次mask的渲染操作。


image

一次mask發(fā)生了兩次離屏渲染和一次主屏渲染硼啤。即使忽略昂貴的上下文切換籍救,一次mask需要渲染三次才能在屏幕上顯示梧却,這已經(jīng)是普通視圖顯示3陪耗時,若再加上下文環(huán)境切換伴郁,一次mask就是普通渲染的30倍以上
耗時操作晕鹊。問我這個30倍以上

這個數(shù)據(jù)怎么的出來的?當(dāng)我在cell的UIImageView的實例增加到150個卵史,并去掉圓角的時候寸潦,幀數(shù)才跌至28幀每秒易核。雖然不是甚準(zhǔn)確浪默,但至少反映mask這個耗時是無mask操作的耗時的數(shù)十倍的牡直。
應(yīng)對
那么如何應(yīng)對這個問題呢缀匕?不要在滾動視圖使用cornerRadius或者mask。如果你非要作死怎么辦呢碰逸?那么這樣也可以拯救你:
self.layer.shouldRasterize = YES; self.layer.rasterizationScale = [UIScreen mainScreen].scale;

這樣大部分情況下可以馬上挽救你的幀數(shù)在55幀每秒以上乡小。shouldRasterize = YES
會使視圖渲染內(nèi)容被緩存起來,下次繪制的時候可以直接顯示緩存饵史,當(dāng)然要在視圖內(nèi)容不改變的情況下满钟。
除了上面非要作死的人外,大家還是采取預(yù)先生成圓角圖片胳喷,并緩存起來這個方法才是比較好的手段湃番。預(yù)處理圓角圖片可以在后臺處理,處理完畢后緩存起來厌蔽,再在主線程顯示牵辣,這就避免了不必要的離屏渲染了。
另外也有在圖片上面覆蓋一個鏤空圓形圖片的方法可以實現(xiàn)圓形頭像效果奴饮,這個也是極為高效的方法。缺點就是對視圖的背景有要求择浊,單色背景效果就最為理想戴卜。
總結(jié)
實現(xiàn)圓角cornerRadius要比mask高效很多。
Rasterize在大部分情況下極大減少GPU工作琢岩。在有空間的情況下投剥,大部分情況下緩存總能幫到你,不是嗎担孔?
后臺預(yù)處理圖片也能很簡單幫上你很大的忙江锨。

(以上測試數(shù)據(jù)來自于iPhone5。)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糕篇,一起剝皮案震驚了整個濱河市啄育,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拌消,老刑警劉巖挑豌,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異墩崩,居然都是意外死亡氓英,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門鹦筹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铝阐,“玉大人,你說我怎么就攤上這事铐拐∨羌” “怎么了练对?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長啊鸭。 經(jīng)常有香客問我锹淌,道長,這世上最難降的妖魔是什么赠制? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任赂摆,我火速辦了婚禮,結(jié)果婚禮上钟些,老公的妹妹穿的比我還像新娘烟号。我一直安慰自己,他們只是感情好政恍,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布汪拥。 她就那樣靜靜地躺著,像睡著了一般篙耗。 火紅的嫁衣襯著肌膚如雪迫筑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天宗弯,我揣著相機與錄音脯燃,去河邊找鬼。 笑死蒙保,一個胖子當(dāng)著我的面吹牛辕棚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播邓厕,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼逝嚎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了详恼?” 一聲冷哼從身側(cè)響起补君,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎单雾,沒想到半個月后赚哗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡硅堆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年屿储,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渐逃。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡够掠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茄菊,到底是詐尸還是另有隱情疯潭,我是刑警寧澤赊堪,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站竖哩,受9級特大地震影響哭廉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜相叁,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一遵绰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧增淹,春花似錦椿访、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拳喻,卻和暖如春哭当,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冗澈。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工荣病, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渗柿。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像脖岛,于是被迫代替她去往敵國和親朵栖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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

  • 前言 開發(fā)的過程遇到需要將很多很多的圖片柴梆,或者Label陨溅,或者Cell......切成圓角,但是數(shù)量多的話绍在,快速滑...
    踐行者_Leng閱讀 307評論 0 0
  • 朋友门扇,今天的你,過28歲了嗎偿渡?開始懷念青春了嗎臼寄? 那時候,桌子上堆滿了各科的習(xí)題溜宽,床頭貼著“戰(zhàn)勝自我”之類的座右銘...
    我是東北仁兒閱讀 449評論 0 3
  • 一直以來适揉,都明白留攒,沒人能一直寵溺著你煤惩,可是,每次炼邀,你都要當(dāng)真魄揉,都要相信,慢慢的發(fā)現(xiàn)拭宁,原來想的都只是想的洛退,現(xiàn)實更殘酷...
    蘇薰閱讀 150評論 0 0
  • (一) 我想了你許久 一邊想一邊等 你也不來我夢里 (二) 我從你深情的眸子里逃脫 才發(fā)現(xiàn) 你看不見 (三) 我終...
    玖月授衣閱讀 322評論 0 2
  • 它不是吃的,只是來拍照的
    碉堡了哈閱讀 132評論 0 1