Runtime之方法緩存

我們都知道,在Objective-c里面,調用一個方法,其實在runtime層的時候會翻譯成

     objc_msgSend(receiver, SEL)

可以想象一下,在繼承關系中,一個比較深度的子類去調用父類的父類的父類... ...的方法的時候,如果沒有緩存,每次都會用isa指針去挨個搜索,查找鏈是非常長的,如果類中的方法比較多,比較費時費力,可以看一個比較明顯的例子:

1.png

在這種情況下,如果沒有方法緩存,查找會變得非常耗時。
首先,先看看,方法緩存是放在哪個地方的,在類的定義中就有方法緩存,具體代碼如下:
2.png

3.png

4.png

5.png

所以,是方法緩存是根據來的, 并不是根據具體的類的對象來的。

方法緩存的實現可以到runtime源碼中去看,為了優化性能,objc_msgSend是用匯編來實現的,在objc-msg-arm.s文件中,具體實現的步驟是:

  1. 判斷receiver是否是nil。

  2. 從緩存里面尋找SEL,找到就分發,否則3。

  3. 跳轉到 _objc_msgSend_uncached ,利用 _class_lookupMethodAndLoadCache3 方法(objc-class.mm中,具體可以看下面)尋找SEL。

對應的代碼為:

6.png
7.png

從代碼中可以看到, 如果沒有找到方法緩存,就會跳轉到\_objc\_msg\_uncached這里,里面有\_class\_lookupMethodAndLoadCache3

這個函數的具體的實現如下:

根據注釋可以知道:此方法可以避免再去緩存查找方法,直接去方法列表去找。

8.png
9.png

其中:

  1. mask: 表示當前緩存能達到的最大的size,從0開始,所以total = mask + 1

  2. occupied: 表示占用的內存標志,順便說一句,方法緩存是通過 “散列表” 的形式 實現的,散列表根據 哈希算法來定位位置,所以會產生空位,occupied用來表示已經使用的內存的個數

  3. buckets:就是用數組來表示存儲緩存的散列表的存儲空間,其中的每一個Method類型表示一個可用的方法緩存。

    注意:其中結構體中,最后一個成員用[1], 說明中這是一個“可變數組”,在我以前接觸到的c語言中,發現有的平臺是用[0]來表示,有的是用[1]來表示可變數組

具體到Method的定義:

10.png
11.png
  1. name: 表示被緩存的方法名字

  2. types: 存儲著方法的的參數類型和返回值類型

  3. imp: 就是方法的具體實現

還有,往散列表中 存方法緩存取方法緩存

  1. 存方法緩存是在objc-cache-old.mm文件中實現的,
    12.png
13.png

這里就是往散列表中存儲的具體實現,其中的散列查找算法是:

14.png

位置是通過sel指針偏移后和mask與后的結果得出

  1. 從緩存中取方法
    取緩存的代碼是 跟objc_msgSend的實現在同一個文件中,obj-msg-arm.s中,為了查找的性能優化,也是通過匯編來實現的,方法名字是 CacheLookup,具體實現是:
15.png
16.png

根據查閱其中的 匯編關鍵字 以及注釋,可以知道,取緩存和加緩存的邏輯差不多,也是根據hash去定位,如果出現沖突,根據解決hash沖突規則,繼續hash, 直到找到為止,這里是 ++ 的實現形式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,788評論 0 9
  • objc_getAssociatedObject返回與給定鍵的特定對象關聯的值。ID objc_getAssoci...
    有一種再見叫青春閱讀 1,653評論 0 7
  • 參數自一個指針,指向類的要接收消息的實例。 OP在處理該信息的方法的選擇。 ......可變參數列表包含參數的方法...
    reallychao閱讀 840評論 0 0
  • 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的轉載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,643評論 33 466
  • 黑暗吞噬了月光 仍阻止不了牛郎織女的相會 男人 女人 相擁或是哭泣 時光就悄然在這霓虹閃耀的夜晚荏苒 歡笑 哭泣 ...
    天涼余燼閱讀 181評論 0 0