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

74 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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