lab/note/资源/编程/Golang/底层架构.md
张育新 241a7c43da docs(note): 新增 excel/正则/Nginx 笔记并整理目录
- 新增 AGENTS.md 仓库说明与 excelize 依赖
- 新增正则表达式、go操作excel、Nginx常见错误、Golang底层架构笔记
- 布尔变量命名迁移至资源/编程/规范,删除随手记旧笔记
2026-08-05 18:32:17 +08:00

4.0 KiB
Raw Blame History

Go 1.24 起,map 的底层实现从传统的 hmap + bmap 哈希表,彻底切换到了 Swiss Table瑞士表

![Gemini_Generated_Image_jhqwi7jhqwi7jhqw](D:\zhangyuxin\code\lab\note\assets\golang-map[swiss table].png)

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 ->  |
| <- 一次性载入寄存器对比 -> |                                                   |

为什么这样设计?(设计优势):

  1. 避免内存对齐填充Padding:如果采用 [Meta][Key][Value] 交叉排列,由于不同类型的 Key/Value 字节大小不同为了对齐Go 必须在它们之间插入大量空白填充字节,浪费空间。分块连续存储消除了组内的对齐损耗。
  2. 对 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)

根据位掩码的匹配结果,执行以下逻辑:

  1. 依次根据匹配成功的索引,去 Key 存储区 找到对应的真实 Key。
  2. 进行完整的 Key 等值对比(如 if key == targetKey若匹配成功:直接去 Value 存储区 对应偏移量取出 Value 并返回。若匹配失败:说明发生了 H2 哈希冲突(即不同的 Key 产生了相同的 H2继续对比下一个匹配的槽位。
  3. 如果当前 Group 中所有匹配了 H2 的槽位都对比完了,仍未找到匹配的 Key跳转至【情况 B】

此时需要检查当前 Group 的 Metadata 状态,决定是继续向后寻找还是停止:

  • 若当前 Group 中存在“空位”Empty0xFF

    说明探测链在此处断开,该 Key 在 Map 中一定不存在,直接返回 nil 或零值。

  • 若当前 Group 中无空位但存在“墓碑”Tombstone0x80或已满

    虽然当前 Group 没找到,但可能因为历史删除操作(留下了墓碑)或哈希冲突,导致数据被存到了后续的 Group。不能停止使用**二次探测算法Quadratic Probing**计算下一个 Group 的索引,跳转回 【3.组内快速匹配】 继续循环寻找。