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

news2025/1/16 9:02:42

1. 关联对象存储(AssociationsHashMap)

// 关联对象的哈希表实现
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)

// 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)

// 弱引用哈希表
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)

// 类的方法缓存
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. 性能优化

// 使用 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 线程安全

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

6.2 内存管理

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

6.3 哈希优化

// 优化的哈希函数
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 冲突处理

// 开放寻址法
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 扩容策略

// 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 内存管理

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

8. 性能考虑

8.1 查找效率

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

8.2 空间效率

// 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. 选择适当的扩容策略

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2277467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从论文到实践:Stable Diffusion模型一键生成高质量AI绘画

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月24日10点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 AI绘画一键生成美图-变成画家 本地部…

业务幂等性技术架构体系之消息幂等深入剖析

在系统中当使用消息队列时&#xff0c;无论做哪种技术选型&#xff0c;有很多问题是无论如何也不能忽视的&#xff0c;如&#xff1a;消息必达、消息幂等等。本文以典型的RabbitMQ为例&#xff0c;讲解如何保证消息幂等的可实施解决方案&#xff0c;其他MQ选型均可参考。 一、…

【2024年华为OD机试】 (B卷,100分)- 跳房子I(Java JS PythonC/C++)

一、问题描述 题目描述 跳房子&#xff0c;也叫跳飞机&#xff0c;是一种世界性的儿童游戏。 游戏参与者需要分多个回合按顺序跳到第1格直到房子的最后一格。 跳房子的过程中&#xff0c;可以向前跳&#xff0c;也可以向后跳。 假设房子的总格数是count&#xff0c;小红每…

鸿蒙打包发布

HarmonyOS应用/元服务发布&#xff08;打包发布&#xff09; https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/ide-publish-app-V13?catalogVersionV13 密钥&#xff1a;包含非对称加密中使用的公钥和私钥&#xff0c;存储在密钥库文件中&#xff0c;格式…

JAVA:在IDEA引入本地jar包的方法(不读取maven目录jar包)

问题&#xff1a; 有时maven使用的jar包版本是最新版&#xff0c;但项目需要的是旧版本&#xff0c;每次重新install会自动将mavan的jar包覆盖到项目的lib目录中&#xff0c;导致项目报错。 解决&#xff1a; 在IDEA中手动配置该jar包对应的目录。 点击菜单File->Projec…

Mac上安装Label Studio

在Mac上安装Anaconda并随后安装Label Studio&#xff0c;可以按照以下步骤进行&#xff1a; 1. 在Mac上安装Anaconda 首先&#xff0c;你需要从Anaconda的官方网站下载适用于Mac的安装程序。访问Anaconda官网&#xff0c;点击“Download Anaconda”按钮&#xff0c;选择适合M…

docker-compose和docker仓库

一、docker-compose 1.概述 docker-compose是一个自动编排工具&#xff0c;可以根据dockerfile自动化部署docker容器。 主要功能 配置定义 使用YAML文件&#xff08;通常命名为docker - compose.yml&#xff09;来描述应用程序的服务、网络和卷等配置。 容器编排 可以同时…

了解linux中的“of_property_read_u32()”

of_property_read_u32(node, "post-pwm-on-delay-ms",&data->post_pwm_on_delay); /*根据"post-pwm-on-delay-ms"&#xff0c;从属性中查找并读取一个32位整数*/ /*读到一个32位整数,保存到data->post_pwm_on_delay中*/ of_property_read_u32…

nodejs 037: 前端新手教程使用引导库 Intro.js

Intro.js简介 Intro.js 是一个流行的引导库&#xff0c;用于提供步进式的新手教程。它可以帮助你创建用户引导&#xff0c;展示一些步骤和提示&#xff0c;逐步引导用户了解应用程序的功能。 安装方法&#xff1a; npm install intro.js使用方法&#xff1a; import introJ…

Vue篇-07

Vue UI组件库 一、移动端常用的UI组件库 1.1、Vant 1.2、Cube UI 1.3、Mint UI 二、PC端常用的UI组件库 2.1、Element UI Element - The worlds most popular Vue UI framework 安装&#xff1a; 按需引入&#xff1a; 135_尚硅谷Vue技术_element-ui按需引入_哔哩哔哩_b…

适配器模式案例

如果在这样的结构中 我们在Controller中注入&#xff0c;但我们后续需要修改Oss时&#xff0c;比如从minioService改成AliyunService时&#xff0c;需要改动的代码很多。于是我们抽象出一个FileService&#xff0c;让controller只跟fileservice耦合&#xff0c;这样我没只需要在…

鸿蒙UI开发——键盘弹出避让模式设置

1、概 述 我们在鸿蒙开发时&#xff0c;不免会遇到用户输入场景&#xff0c;当用户准备输入时&#xff0c;会涉及到输入法的弹出&#xff0c;我们的界面针对输入法的弹出有两种避让模式&#xff1a;上抬模式、压缩模式。 下面针对输入法的两种避让模式的设置做简单介绍。 2、…

Vue2+OpenLayers实现折线绘制功能(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、初始变量 3.2、画一条折线 3.3、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 3.1、初始变量 关键代码&#xff1a; data() {return {map:null,// 定义路径坐…

栈算法篇——LIFO后进先出,数据与思想的层叠乐章(上)

文章目录 前言第一章&#xff1a;栈的基础知识回顾1.1 栈的结构与实现1.2 栈的应用第二章&#xff1a;删除字符串中的所有相邻重复项2.1 题目链接&#xff1a;https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/description/2.2 题目分析&#xff1a;2.3…

计算机的错误计算(二百一十二)

摘要 利用两个大模型计算 实验表明&#xff0c;两个大模型均进行了中肯的分析。另外&#xff0c;其中一个大模型给出了 Python代码&#xff0c;运行后&#xff0c;结果中有7位错误数字&#xff1b;而一个大模型进行加减运算时出错。 例1. 计算 下面是与一个大模型的对话…

VMware虚拟机安装Home Assistant智能家居平台并实现远程访问保姆级教程

目录 前言 1. 安装Home Assistant 前言 本文主要介绍如何在windows 10 上用VMware Workstation 17 Pro搭建 Home Assistant OS Host os version&#xff1a;Windows 10 Pro, 64-bit (Build 19045.5247) 10.0.19045 VMware version:VMware Workstation 17 Pro 1. 安装Home …

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载,Scroll滚动到顶部

HarmonyOS 鸿蒙 ArkTs(5.0.1 13)实现Scroll下拉到顶刷新/上拉触底加载 效果展示 使用方法 import LoadingText from "../components/LoadingText" import PageToRefresh from "../components/PageToRefresh" import FooterBar from "../components/…

【开源免费】基于Vue和SpringBoot的欢迪迈手机商城(附论文)

本文项目编号 T 141 &#xff0c;文末自助获取源码 \color{red}{T141&#xff0c;文末自助获取源码} T141&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

Cyber Security 101-Offensive Security-SQLMap: The Basics(sqlmap基础)

了解 SQL 注入并通过 SQLMap 工具利用此漏洞。 任务1&#xff1a;介绍 SQL 注入是一个普遍存在的漏洞&#xff0c;长期以来一直是热门 网络安全主题。要了解这个漏洞&#xff0c;我们必须首先 了解什么是数据库以及网站如何与数据库交互。 数据库是可以存储、修改和 检索。它…

【数据结构-堆】力扣1792. 最大平均通过率

一所学校里有一些班级&#xff0c;每个班级里有一些学生&#xff0c;现在每个班都会进行一场期末考试。给你一个二维数组 classes &#xff0c;其中 classes[i] [passi, totali] &#xff0c;表示你提前知道了第 i 个班级总共有 totali 个学生&#xff0c;其中只有 passi 个学…