iOS效能優化 非同步繪製

2022-06-03 10:54:08 字數 2422 閱讀 3020

通讀下來可以總結一下對效能優化,在這裡也就是提高介面流暢度的宗旨只有一句話唯而已:把能非同步執行的都盡量非同步執行.

yyfpslabel拿過來用了,檢測fps的變化情況:

可以看到,在滑動很快的時候,fps最低已經達到了20幾.

經過非同步繪製處理之後,可以看到無論如何滑動,fps一直保持在60.

這是我寫的乙個小demo:也就是上面執行案例的**.

前後對比的效果就是將cell中的label使用uilabel和使用自定義label之後的效果.

首先,其實這種優化是對流暢度非常敏感的介面來說的,一般場景很少需要做這樣的優化,並且,只有在文字非常多且複雜,滑動非常快的時候才能明顯的感覺到差別.

如果專案中某個地方需要優化,而你也想嘗試一下使用yyasynclayer,並且對文字的處理比較簡單,可以將demo中的atlabel拿來參考,當然直接使用yylabel是最好的選擇,atlabel只是用來演示yyasynclayer的使用,並且非常簡陋.

不談yylabel內部各種複雜的處理,他是直接繼承自uiview,自己造了個label控制項出來,但是從非同步繪製的角度來說,其原理就是,將本來uilabel所做的繪製文字的工作拿過來自己做,並放在子執行緒非同步執行.

下面簡單分析一下yyasynclayer的內部原理:

其中涉及到了四個類:

yyasynclayer

yytransaction

yysentinel

yydispatchqueuepool

先從yytransaction開始說起,每乙個yytransaction物件相當於乙個非同步繪製任務.

atlabel中在以下需要呼叫重繪的方法中都提交了contentsneedupdated任務,

檢視commit方法可以看到,他使用了乙個set來儲存這些任務.並且在其中呼叫了乙個方法:

看一下yytransactionsetup方法:

可以看到這個方法中的**只會執行一次,也就是在第一次commit 的時候執行一次,之後便不會再執行了.方法內部初始化了乙個set物件,用來收集繪製任務,並做了runloop監聽,在runloop等待和退出之前,也就是空閒的時候,呼叫**方法.

而在這個**方法中,便是執行所有收集到的繪製任務.

綜上所述,在label需要重繪的時候,作者將繪製任務收集起來,並在runloop空閒的時候一起執行.

接下來看一下作者是如何執行這些任務的:

可以看到每個繪製任務都是呼叫display方法,而display中執行的

_displayasync

方法便是對非同步繪製的處理,也就是說每個繪製任務最終都會呼叫到這個方法.

方法:

在atlabel中可以看到

作者重寫了layerclass方法,並返回了yyasynclayer.class,也就是將當前label的layer替換為了yyasynclayer.然後便可以通過實現yyasynclayer的**方法

newasyncdisplaytask.將atlabel我們自己對文字繪製的實現非同步執行.

上面圈出來的便是對**中我們task.display**實現的呼叫.,可以看到是在非同步**塊中.

回到yyasynclayer的 _displayasync方法,可以看到最後回到主線程將繪製內容賦值,便完成了整個流程.

最後,還有作者一些細節性的處理我沒有寫下來,有興趣可以自己研究一下,比如計數器的使用,hash的處理,佇列數量的控制,cancel()的處理,還有一些繪製相關的工作,作者短短的幾百行**凝聚了很多智慧型.

其他:貝塞爾曲線非同步繪製圓角:

效能優化過度繪製

過度繪製對效能會產生不必要的開銷,如果能減少不必要的繪製,將有助於效能的提公升。以下以在手機上進行 debug gpu overdraw 舉例 看到整個螢幕有顏色變化就對了 1 這裡有四層顏色的指示,顏色的層級表示螢幕上有多少畫素過度繪製 什麼是過度繪製,假設你在根檢視viewgroup match...

效能優化 iOS

如果需要更詳細的資訊,那就將dyld print statistics details設定為1 2.1關於dyld 用machoview 檢視載入過程如上圖 備註1 如果設定了 dyld print libraries,或者選中run diagnostics 下面的 dynamic library ...

springBoot 效能優化 非同步響應

業務開發中,有很多場景會有比較耗時的操作 比如需要呼叫第三方介面查詢資料 發郵件等 都有可能需要1秒以上的時間 如果按照傳統的方式處理,即是執行緒阻塞1秒以上的時間去等待結果,再把結果返回給使用者 而且處理請求的執行緒池中線程數總是有限的,如果執行緒都阻塞在等待中,後續的請求只能排隊等候 這也就影響...