Runtime底層解析 - 方法緩存 :cache

  • Class內(nèi)部結(jié)構(gòu)中有個(gè)方法緩存(cache_t),用散列表(哈希表)來(lái)緩存曾經(jīng)調(diào)用過(guò)的方法,可以提高方法的查找速度。
struct cache_t {
    struct bucket_t *_buckets; //散列表 (bucket_t, ...)
    mask_t _mask; //散列表的長(zhǎng)度 - 1
    mask_t _occupied; //已經(jīng)緩存的方法數(shù)量
};
|
|
struct bucket_t {
    cache_key_t _key; // SEL作為Key
    IMP _imp;  //函數(shù)的內(nèi)存地址
};
  • 緩存查找:bucket_t * cache_t::find(cache_key_t k, id receiver)


散列表(哈希表)

散列表找元素的原理:
  • f(key) = index
  • 通過(guò)一個(gè)函數(shù),傳入一個(gè)key,算出一個(gè)索引index。
  • 如果這個(gè)索引沖突了,那就通過(guò)+ 1 、- 1或某個(gè)算法再算一遍,直到不沖突為止。
應(yīng)用
  • 在存儲(chǔ)bucket_t時(shí),將這個(gè)_key&_mask得到一個(gè)值,方法就存在相應(yīng)的位置;
  • 取方法時(shí),也是直接_key&_mask,去對(duì)應(yīng)的值里取bucket_t;
static inline mask_t cache_hash(cache_key_t key, mask_t mask) 
{
    return (mask_t)(key & mask);
}
  • 由圖表看到好多空間沒(méi)有使用到,故,這是一種犧牲空間使用效率,來(lái)?yè)Q取查詢效率的方法。

_key&_mask的結(jié)果和之前的重復(fù)了怎么辦 ?

即: _key&_mask 之后,該位置上已經(jīng)有bucket_t了或者取出來(lái)的bucket_t_key對(duì)不上。

解決:

以存為例:

  • 得出的值,位置有bucket_t;
  • - 1 ,如果還有,繼續(xù)-1;
  • 值 = 0 ,就直接等于maskmask == 散列表的長(zhǎng)度 - 1)。
static inline mask_t cache_next(mask_t i, mask_t mask) {
    return i ? i-1 : mask;
}

如果方法過(guò)多,散列表原來(lái)的長(zhǎng)度不夠了怎么辦?
  • 擴(kuò)容為原來(lái)空間的2倍;
  • 將原緩存清空。
void cache_t::expand()
{
    cacheUpdateLock.assertLocked();
    
    uint32_t oldCapacity = capacity();
    uint32_t newCapacity = oldCapacity ? oldCapacity*2 : INIT_CACHE_SIZE; // 2倍
     .........
   reallocate(oldCapacity, newCapacity); //里面有個(gè)" cache_collect_free(oldBuckets, oldCapacity);"
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容