iOS - Objective-C 底层实现中的哈希表

1. 关联对象存储(AssociationsHashMap)

objectivec 复制代码
// 关联对象的哈希表实现
typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;

class AssociationsManager {
    static AssociationsHashMap *_map;  // 全局关联对象表
    
    void set(id object, const void *key, id value) {
        // 双层 map:对象 -> (key -> value)
        AssociationsHashMap::iterator i = _map->find(object);
        if (i != _map->end()) {
            ObjectAssociationMap &refs = i->second;
            refs[key] = ObjcAssociation(value);
        }
    }
};

// 特点:
// 1. 双层哈希表结构
// 2. 使用 DenseMap 实现
// 3. 支持动态扩容

注意事项:

  • 需要考虑内存开销
  • 多层查找可能影响性能
  • 需要正确管理关联对象的生命周期

2. 引用计数表(RefcountMap)

objectivec 复制代码
// SideTable 中的引用计数表
class SideTable {
    RefcountMap refcnts;  // 存储对象的引用计数
    
    void retain(id obj) {
        RefcountMap::iterator it = refcnts.find(obj);
        if (it != refcnts.end()) {
            it->second += SIDE_TABLE_RC_ONE;
        }
    }
};

typedef objc::DenseMap<DisguisedPtr<objc_object>, size_t> RefcountMap;

// 特点:
// 1. 使用 DenseMap 实现
// 2. Key 使用伪装指针
// 3. 需要频繁访问和修改

注意事项:

  • 需要保证原子性操作
  • 性能要求高
  • 内存管理要谨慎

3. 弱引用表(weak_table_t)

objectivec 复制代码
// 弱引用哈希表
struct weak_table_t {
    weak_entry_t *weak_entries;  // 哈希数组
    size_t num_entries;          // 实际条目数
    uintptr_t mask;             // 容量掩码
    uintptr_t max_hash_displacement; // 最大哈希偏移
    
    weak_entry_t *get(id referent) {
        // 使用哈希查找
        size_t begin = hash_pointer(referent) & mask;
        size_t index = begin;
        size_t hash_displacement = 0;
        while (weak_entries[index].referent != referent) {
            index = (index + 1) & mask;
            if (index == begin) break;
            hash_displacement++;
        }
        return &weak_entries[index];
    }
};

// 特点:
// 1. 开放寻址法处理冲突
// 2. 使用线性探测
// 3. 记录最大偏移量

注意事项:

  • 需要控制装载因子,避免性能下降
  • 删除元素时需要特殊处理,避免破坏探测链
  • 扩容时需要重新哈希所有元素

4. 方法缓存(cache_t)

objectivec 复制代码
// 类的方法缓存
struct cache_t {
    struct bucket_t *_buckets;  // 哈希表
    mask_t _mask;              // 容量掩码
    mask_t _occupied;          // 已使用数量
    
    IMP imp(SEL sel) {
        // 使用哈希查找方法实现
        bucket_t *b = buckets();
        mask_t m = mask();
        return findMethod(b, m, sel);
    }
};

// 特点:
// 1. 采用散列函数直接寻址
// 2. 缓存最近使用的方法
// 3. 固定大小,满了就清空重建

注意事项:

  • 缓存满时会清空重建,而不是扩容
  • 性能敏感,需要快速查找
  • 线程安全问题需要特别注意

5. 性能优化

objectivec 复制代码
// 使用 DenseMap 优化内存使用
template <typename T, typename U, typename V>
class DenseMap {
    // 1. 开放寻址法处理冲突
    pair<iterator, bool> insert(const T& key, const U& value) {
        // 查找空位置
        unsigned index = findEmptyBucket(key);
        // 插入数据
        Buckets[index] = make_pair(key, value);
    }
    
    // 2. 自动扩容
    void grow() {
        unsigned NewSize = size() * 2;
        rehash(NewSize);
    }
};

6. 使用特点

6.1 线程安全

objectivec 复制代码
// 访问 map 时加锁保护
spinlock_t& lock = SideTables()[obj].lock;
lock.lock();
// 操作 map
lock.unlock();

6.2 内存管理

objectivec 复制代码
// 定期清理
void cleanup() {
    // 遍历并清理无效条目
    for (iterator it = map.begin(); it != map.end();) {
        if (it->second.expired()) {
            it = map.erase(it);
        } else {
            ++it;
        }
    }
}

6.3 哈希优化

objectivec 复制代码
// 优化的哈希函数
static inline uint32_t ptr_hash(const void *key) {
    uintptr_t k = (uintptr_t)key;
    return (uint32_t)(k ^ (k >> 7));
}

主要使用场景总结:

  1. 关联对象存储
  2. 引用计数管理
  3. 弱引用表实现
  4. 方法缓存
  5. 性能优化

使用特点:

  1. 多采用 DenseMap 实现
  2. 注重性能优化
  3. 考虑线程安全
  4. 自动内存管理
  5. 哈希冲突处理

7. 实现差异

7.1 冲突处理

objectivec 复制代码
// 开放寻址法
void insert(Key key, Value value) {
    size_t index = hash(key) & mask;
    while (table[index] != empty) {
        index = (index + 1) & mask;  // 线性探测
    }
    table[index] = value;
}

// 链地址法
void insert(Key key, Value value) {
    size_t index = hash(key) & mask;
    table[index].push_back(value);  // 添加到链表
}

7.2 扩容策略

objectivec 复制代码
// weak_table_t 的扩容
void grow() {
    // 当使用率超过 3/4 时扩容
    if (num_entries >= capacity * 3/4) {
        resize(capacity * 2);
    }
}

// cache_t 的重建
void rebuild() {
    // 缓存满时直接清空重建
    clear();
    allocate(capacity);
}

7.3 内存管理

objectivec 复制代码
// DenseMap 的内存管理
template <typename Key, typename Value>
class DenseMap {
    // 使用连续内存
    pair<Key, Value> *Buckets;
    
    // 自动扩容
    void grow() {
        reallocate(NumEntries * 2);
    }
};

8. 性能考虑

8.1 查找效率

objectivec 复制代码
// 方法缓存优化
IMP cache_t::imp(SEL sel) {
    // 使用位运算优化
    mask_t index = (mask_t)(uintptr_t)sel & _mask;
    return _buckets[index].imp();
}

8.2 空间效率

objectivec 复制代码
// weak_table_t 的空间优化
struct weak_entry_t {
    union {
        struct {
            weak_referrer_t *referrers;      // 动态数组
        };
        struct {
            weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT]; // 内联存储
        };
    };
};

总结:

  1. 不同场景选择不同的哈希表实现
  2. 需要权衡时间和空间效率
  3. 要考虑线程安全问题
  4. 注意内存管理和性能优化
  5. 合理处理哈希冲突
  6. 选择适当的扩容策略
相关推荐
Jouzzy1 小时前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
瓜子三百克1 小时前
采用sherpa-onnx 实现 ios语音唤起的调研
macos·ios·cocoa
左钦杨2 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
努力成为包租婆4 小时前
SDK does not contain ‘libarclite‘ at the path
ios
安和昂21 小时前
【iOS】Tagged Pointer
macos·ios·cocoa
٩( 'ω' )و2601 天前
哈希表的实现01
数据结构·c++·哈希算法·散列表
学习中的码虫1 天前
c 中的哈希表
数据结构·哈希算法·散列表
I烟雨云渊T1 天前
iOS 阅后即焚功能的实现
macos·ios·cocoa
struggle20251 天前
适用于 iOS 的 开源Ultralytics YOLO:应用程序和 Swift 软件包,用于在您自己的 iOS 应用程序中运行 YOLO
yolo·ios·开源·app·swift
Unlimitedz1 天前
iOS视频编码详细步骤(视频编码器,基于 VideoToolbox,支持硬件编码 H264/H265)
ios·音视频