- 新增 AGENTS.md 仓库说明与 excelize 依赖 - 新增正则表达式、go操作excel、Nginx常见错误、Golang底层架构笔记 - 布尔变量命名迁移至资源/编程/规范,删除随手记旧笔记
4.0 KiB
4.0 KiB
Go 1.24 起,map 的底层实现从传统的 hmap + bmap 哈希表,彻底切换到了 Swiss Table(瑞士表)

Group内存布局图
你可以直接复制以下文本块到你的 Markdown 笔记中(使用 text 包裹):
codeText
+-------------------------------------------------------------------------------+
| 单 Group 内存布局 |
+--------------------------+----------------------------+-----------------------+
| 1. Metadata 控制字节区 | 2. 连续 Key 存储区 | 3. 连续 Value 存储区 |
+--------------------------+----------------------------+-----------------------+
| [M0][M1][M2]...[M7] | [K0][K1][K2]...[K7] | [V0][V1][V2]...[V7] |
+--------------------------+----------------------------+-----------------------+
| <- 固定 8 个字节 -> | <- 长度取决于 Key 类型 -> | <- 长度取决于 Val -> |
| <- 一次性载入寄存器对比 -> | |
为什么这样设计?(设计优势):
- 避免内存对齐填充(Padding):如果采用 [Meta][Key][Value] 交叉排列,由于不同类型的 Key/Value 字节大小不同,为了对齐,Go 必须在它们之间插入大量空白填充字节,浪费空间。分块连续存储消除了组内的对齐损耗。
- 对 CPU 缓存友好:8 字节的 Metadata 紧密相连,一次 Cache Line 填充就能把整组的控制信息全部读入,极大地提高了缓存命中率。
读取流程
以下为您整理的完整、正确的读取逻辑,您可以直接复制使用:
1.哈希计算与分段 (Hash Splitting)
- 将 Key 传入哈希函数,计算出一个 64 位的哈希值。
- 该哈希值被拆分为两部分:H1(高 57 位):用于定位哈希表中的初始 Group 索引。H2(低 7 位):作为特征值(指纹),存储在 Group 的 Metadata 中,用于快速匹配。
2.定位初始 Group (Locate Group)
-
计算初始 Group 索引:group_index = H1 & (Group数量 - 1)。
可以理解与$2^B$进行取模运算,但是位与运算效率更高且等价。
3.组内快速匹配 (Group-level SWAR Match)
- 一次性加载:将目标 Group 的 8 字节 Metadata 一次性载入一个 64 位寄存器中。
- 并行对比(SWAR 技术):利用位运算,将 7 位的 H2 同时与这 8 个 Metadata 字节进行并行对比,输出一个 8 位的位掩码(Bitmask)。位掩码中为 1 的位,代表该位置的 H2 与目标 H2 匹配成功。这一步极快,完全避免了循环遍历。
4.冲突解决与探测循环 (Verification & Probing Loop)
根据位掩码的匹配结果,执行以下逻辑:
- 依次根据匹配成功的索引,去 Key 存储区 找到对应的真实 Key。
- 进行完整的 Key 等值对比(如 if key == targetKey):若匹配成功:直接去 Value 存储区 对应偏移量取出 Value 并返回。若匹配失败:说明发生了 H2 哈希冲突(即不同的 Key 产生了相同的 H2),继续对比下一个匹配的槽位。
- 如果当前 Group 中所有匹配了 H2 的槽位都对比完了,仍未找到匹配的 Key,则跳转至【情况 B】。
此时需要检查当前 Group 的 Metadata 状态,决定是继续向后寻找还是停止:
-
若当前 Group 中存在“空位”(Empty,0xFF):
说明探测链在此处断开,该 Key 在 Map 中一定不存在,直接返回 nil 或零值。
-
若当前 Group 中无空位,但存在“墓碑”(Tombstone,0x80)或已满:
虽然当前 Group 没找到,但可能因为历史删除操作(留下了墓碑)或哈希冲突,导致数据被存到了后续的 Group。不能停止!使用**二次探测算法(Quadratic Probing)**计算下一个 Group 的索引,跳转回 【3.组内快速匹配】 继续循环寻找。