? ?導(dǎo)讀:
離屏渲染在開發(fā)中帶來(lái)界面卡頓問題一直讓開發(fā)者們頭疼.今天在這里寫一遍關(guān)于離屏渲染的博文.希望大家有所收獲
現(xiàn)在的iOS開發(fā)越來(lái)越注重App性能和用戶體驗(yàn)了.
性能優(yōu)化和內(nèi)存管理是iOS面試中必問的兩道面試題.也是編程中最難的部分之一
要想知道如何解決界面卡頓問題,那你必須對(duì)離屏渲染有所了解
要想成為一個(gè)高級(jí)iOS程序員,你必須學(xué)會(huì)如何性能優(yōu)化,內(nèi)存優(yōu)化
讀懂了這篇文章,掌握離屏渲染的原理,讓你的App從此遠(yuǎn)離卡頓.
OpenGL中,GPU屏幕渲染有以下兩種方式:
一.On-Screen Rendering
? ? ? 意為當(dāng)前屏幕渲染,指的是GPU的渲染操作是在當(dāng)前用于顯示的屏幕緩沖區(qū)中進(jìn)行橙喘。
當(dāng)前屏幕渲染是不需要額外創(chuàng)建新的緩存.也不需要開啟新的上下文.相較與離屏渲染,性能更好.
? ? ? 但是受當(dāng)前屏幕渲染的局限因素限制(只有自身上下文,屏幕緩存有限等),很對(duì)圖形渲染,當(dāng)前屏幕渲染是解決不了的.這時(shí)必須使用到離屏渲染.如何正確的使用離屏渲染,下面會(huì)為你詳細(xì)描述
二.Off-Screen Rendering
? ? ? 意為離屏渲染彩扔,指的是GPU在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作煮仇。
特殊的“離屏渲染”:CPU渲染
? ? ? 如果我們重 寫了drawRect方法岖食,并且使用任何Core Graphics的技術(shù)進(jìn)行了繪制操作啸胧,就涉及到了CPU渲染铛绰。整個(gè)渲染過程由CPU在App內(nèi)同步地完成诈茧,渲染得到的bitmap(位圖)最后再交由GPU用于 顯示。
普通的離屏渲染
相比于當(dāng)前屏幕渲染捂掰,離屏渲染的代價(jià)是很高的敢会,主要體現(xiàn)在兩個(gè)方面:
1.創(chuàng)建新緩沖區(qū)
要想進(jìn)行離屏渲染,首先要?jiǎng)?chuàng)建一個(gè)新的緩沖區(qū)这嚣。
2.上下文切換
離屏渲染的整個(gè)過程鸥昏,需要多次切換上下文環(huán)境:先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后姐帚,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上有需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕吏垮。而上下文環(huán)境的切換是要付出很大代價(jià)的。
設(shè)置了以下屬性時(shí)罐旗,都會(huì)觸發(fā)離屏繪制:
1.shouldRasterize(光柵化)
2.masks(遮罩)
3.shadows(陰影)
4.edge antialiasing(抗鋸齒)
5.group opacity(不透明)
需要注意的是膳汪,如果shouldRasterize被設(shè)置成YES,在觸發(fā)離屏繪制的同時(shí)九秀,會(huì)將光柵化后的內(nèi)容緩存起來(lái)旅敷,如果對(duì)應(yīng)的layer及其sublayers沒有發(fā)生改變,在下一幀的時(shí)候可以直接復(fù)用颤霎。這將在很大程度上提升渲染性能媳谁。
而其它屬性如果是開啟的,就不會(huì)有緩存友酱,離屏繪制會(huì)在每一幀都發(fā)生晴音。
在開發(fā)時(shí)需要根據(jù)實(shí)際情況來(lái)選擇最優(yōu)的實(shí)現(xiàn)方式,盡量使用On-Screen Rendering缔杉。簡(jiǎn)單的Off-Screen Rendering可以考慮使用Core Graphics讓CPU來(lái)渲染锤躁。
如何抉擇
現(xiàn)在擺在我們面前得有三個(gè)選擇:當(dāng)前屏幕渲染、離屏渲染或详、CPU渲染系羞,該用哪個(gè)呢郭计?這需要根據(jù)具體的使用場(chǎng)景來(lái)決定。
盡量使用當(dāng)前屏幕渲染
鑒于離屏渲染椒振、CPU渲染可能帶來(lái)的性能問題昭伸,一般情況下,我們要盡量使用當(dāng)前屏幕渲染澎迎。
離屏渲染 VS CPU渲染
由于GPU的浮點(diǎn)運(yùn)算能力比CPU強(qiáng)庐杨,CPU渲染的效率可能不如離屏渲染;但如果僅僅是實(shí)現(xiàn)一個(gè)簡(jiǎn)單的效果夹供,直接使用CPU渲染的效率又可能比離屏渲染好,畢竟普通的離屏渲染要涉及到緩沖區(qū)創(chuàng)建和上下文切換等耗時(shí)操作灵份。普通的離屏繪制是發(fā)生在繪制服務(wù)(是獨(dú)立的處理過程)并且同時(shí)通過GPU執(zhí)行。當(dāng)OpengGL的繪制程序在繪制每個(gè)layer的時(shí)候哮洽,有可能因?yàn)榘嘧訉蛹?jí)關(guān)系而必須停下來(lái)把他們合成到一個(gè)單獨(dú)的緩存里填渠。你可能認(rèn)為GPU應(yīng)該總是比CPU牛逼一點(diǎn),但是在這里我們還是需要慎重的考慮一下鸟辅。因?yàn)閷?duì)GPU來(lái)說揭蜒,從當(dāng)前屏幕(on-screen)到離屏(off-screen)上下文環(huán)境的來(lái)回切換,代價(jià)是非常大的剔桨。因此對(duì)一些簡(jiǎn)單的繪制過程來(lái)說,這個(gè)過程有可能用CoreGraphics徙融,全部用CPU來(lái)完成反而會(huì)比GPU做得更好洒缀。所以如果你正在嘗試處理一些復(fù)雜的層級(jí),并且在猶豫到底用-[CALayer?setShouldRasterize:]?還是通過CoreGraphics來(lái)繪制層級(jí)上的所有內(nèi)容欺冀,唯一的方法就是測(cè)試并且進(jìn)行權(quán)衡树绩。
總之,具體的選擇應(yīng)該由性能測(cè)試結(jié)果來(lái)決定隐轩。
簡(jiǎn)而言之:
如果覺得前面的過于抽象,沒看懂,不要緊,把下面的看懂就能正確的解決離屏渲染帶來(lái)的界面卡頓的問題了
1.盡量使用當(dāng)前屏幕渲染,能不使用離屏渲染則盡量不用,你應(yīng)當(dāng)盡量避免使用 layer 的 border饺饭、corner、shadow职车、mask 等技術(shù).
2.必須離屏渲染時(shí),相對(duì)簡(jiǎn)單的視圖應(yīng)該使用cpu渲染,相對(duì)復(fù)雜的視圖則使用一般的離屏渲染.