前言
????????在WWDC20中,蘋果官方介紹了對類的修改,其中出現(xiàn)了一個新的結(jié)構(gòu)?class_rw_ext_t,那么為什么會出現(xiàn)這個東東呢?在看這篇文章時,希望你是閱讀過runtime源碼的。
Why?
? ? ? ? 首先,我們先來了解下,clean memory 與 dirty memory的區(qū)別:
? ? ? ? clean memory : 加載后,不會被修改。在內(nèi)存緊張時,可以從內(nèi)存中移除,需要時再次從文件中加載。
? ? ? ? dirty memory : 加載后,會被修改,一直存在于內(nèi)存中,所以dirty memory更加”寶貴“
????????在舊版本的runtime中,類一旦被加載到內(nèi)存中,就會初始化一個rw結(jié)構(gòu),并將所有的ro中的methods,protocols,properties復(fù)制到rw中,rw屬于dirty memory。但大約90%的類并不需要對rw中的methods等進(jìn)行修改,所以這部分”dirty memory“無疑是浪費的。所以蘋果對class_rw_t進(jìn)行進(jìn)一步拆分出class_rw_ext_t用來存儲這部分可能被修改的methods等,而?class_rw_ext_t只有在需要的時候,才被創(chuàng)建。而不被創(chuàng)建的class_rw_ext_t則是優(yōu)化后,相對于舊版runtime可以節(jié)省下的內(nèi)存空間。


How?
? ? ? ? 以“查找方法”為例,對新舊版本runtime進(jìn)行比較:
? ? ? ? 舊版本runtim直接訪問rw的methods屬性,查找方法。在類加載到內(nèi)存時,直接copy了ro的方法列表,所以無論方法列表是否被改變,這塊內(nèi)存都會開辟。


? ? ? ? 新版runtime則是訪問rw的methods()成員方法來獲取類的方法列表,而且在methods方法中判斷了,rw_ext_t是否已經(jīng)初始化了,如果初始化,則讀取class_rw_ext_t的methods,否則從ro的baseMethods()獲取類的方法列表??聪旅娴拇a:


????????總結(jié):新版的rumtime利用了懶加載的機(jī)制,在類的methods,properties等需要修改時,才初始化class_rw_ext_t這塊“dirty+memory”存儲這些列表,這樣就減少了在舊版rumtime中90%的類在rw中直接復(fù)制ro中數(shù)據(jù)浪費的內(nèi)存。
補(bǔ)充:那class_rw_ext_t內(nèi)存又是在何時開辟的呢?
????????1.裝載分類時
????????2.runtime動態(tài)添加方法時
????????3.runtime添加property時
????????4.runtime添加protocol時