Skip to content

Commit 6e3c2a7

Browse files
committed
add diagrams
1 parent 216ed51 commit 6e3c2a7

File tree

1 file changed

+123
-1
lines changed

1 file changed

+123
-1
lines changed

map.md

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ search:
650650
1. 是不是已经到了 load factor 的临界点,即元素个数 >= 桶个数 * 6.5,这时候说明大部分的桶可能都快满了,如果插入新元素,有大概率需要挂在 overflow 的桶上。
651651
2. overflow 的桶是不是太多了,当 bucket 总数 < 2 ^ 15 时,如果 overflow 的 bucket 总数 >= bucket 的总数,那么我们认为 overflow 的桶太多了。当 bucket 总数 >= 2 ^ 15 时,那我们直接和 2 ^ 15 比较,overflow 的 bucket >= 2 ^ 15 时,即认为溢出桶太多了。为啥会导致这种情况呢?是因为我们对 map 一边插入,一边删除,会导致其中很多桶出现空洞,这样使得 bucket 使用率不高,值存储得比较稀疏。在查找时效率会下降。
652652

653-
两种情况官方采用了不同的解决方法:
653+
两种情况官方采用了不同的解决方法:
654654

655655
* 针对 1,将 B + 1,进而 hmap 的 bucket 数组扩容一倍;
656656
* 针对 2,通过移动 bucket 内容,使其倾向于紧密排列从而提高 bucket 利用率。
@@ -930,6 +930,128 @@ func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {
930930
}
931931
```
932932

933+
代码看着比较抽象,再补两个图:
934+
935+
* sameSizeGrow
936+
937+
```
938+
┌──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
939+
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
940+
└──────────┼──────────┴─────┬────┴──────────┴──────────┴──────────┴──────────┴──────────┘
941+
┌────────────────┐ │ tophash: 10 │
942+
│ empty │ │ lowbits: 1001 │
943+
│ │◀─────┐ ├────────────────┤
944+
├────────────────┤ │ │ empty │
945+
│ empty │ │ │ │
946+
│ │ │ ├────────────────┤
947+
├────────────────┤ │ │ empty │
948+
│ empty │ │ │ │
949+
│ │ │ │ ├────────────────┤
950+
│ ├────────────────┤ │ │ tophash: 23 │
951+
│ │ empty │ │ │ lowbits: 0001 │
952+
│ │ │ │ ├────────────────┤
953+
│ ├────────────────┤ │ │ empty │
954+
┌──────────┐ │ │ empty │ │ │ │
955+
│ before │ │ │ │ │ ├────────────────┤
956+
└──────────┘ │ ├────────────────┤ │ │ tophash: 100 │
957+
│ │ empty │ │ │ lowbits: 0001 │
958+
│ │ │ │ ├────────────────┤
959+
│ ├────────────────┤ │ │ empty │
960+
│ │ tophash: 15 │ │ │ │
961+
│ │ lowbits: 0001 │ │ ├────────────────┤
962+
│ ├────────────────┤ │ │ empty │
963+
│ │ empty │ │ │ │
964+
│ │ │ │ ├──────────┬─────┘
965+
│ └────────────────┘ └───────│ overflow │
966+
│ └──────────┘
967+
968+
969+
970+
971+
│ ┌────────────────┐
972+
│ │ tophash: 10 │
973+
│ │ lowbits: 1001 │
974+
│ ├────────────────┤
975+
│ │ tophash: 23 │
976+
│ │ lowbits: 0001 │
977+
│ ├────────────────┤
978+
│ │ tophash: 100 │
979+
│ │ lowbits: 0001 │
980+
│ ├────────────────┤
981+
│ │ tophash: 15 │
982+
│ │ lowbits: 0001 │
983+
│ ├────────────────┤
984+
┌──────────┐ │ │ empty │
985+
│ after │ │ │ │
986+
└──────────┘ │ ├────────────────┤
987+
│ │ empty │
988+
│ │ │
989+
│ ├────────────────┤
990+
│ │ empty │
991+
│ │ │
992+
│ ├────────────────┤
993+
│ │ empty │
994+
│ │ │
995+
│ ┌──────────┼──────────┬─────┴────┬──────────┬──────────┬──────────┬──────────┬──────────┐
996+
│ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
997+
│ ├──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┤
998+
│ │ │
999+
│ │ │
1000+
│ │ │
1001+
│ │ │
1002+
│ │ │
1003+
│ │ │
1004+
│ │ │
1005+
│ │◀───────────────────────────── X part ──────────────────────────────▶│
1006+
│ │ │
1007+
▼ │ │
1008+
│ │
1009+
│ │
1010+
│ │
1011+
```
1012+
1013+
sameSizeGrow 之后,数据排列更紧凑。
1014+
1015+
* biggerSizeGrow
1016+
1017+
```
1018+
┌──────────┐ ┌──────────┬───────────
1019+
│ 0 │ │ 0 │ ▲
1020+
├──────────┼───────────────┬────────────────┐ ├──────────┤ │
1021+
│ 1 │ tophash: 10 │ tophash:23 │ ┌─────▶│ 1 │ │
1022+
├──────────┤ lowbits: 1001 │ low bits: 0001 │──────┘ ├──────────┤ │
1023+
│ 2 ├───────────────┴────────────────┘ │ 2 │ │
1024+
├──────────┤ │ ├──────────┤
1025+
│ 3 │ │ │ 3 │
1026+
├──────────┤ │ ├──────────┤ X part
1027+
│ 4 │ │ │ 4 │
1028+
├──────────┤ │ ├──────────┤
1029+
│ 5 │ │ │ 5 │ │
1030+
├──────────┤ │ ├──────────┤ │
1031+
│ 6 │ │ │ 6 │ │
1032+
├──────────┤ │ ├──────────┤ │
1033+
│ 7 │ │ │ 7 │ ▼
1034+
└──────────┘ │ ├──────────┼───────────
1035+
│ │ 0 │ ▲
1036+
│ ├──────────┤ │
1037+
└─────────────────────────────────────▶│ 1 │ │
1038+
├──────────┤ │
1039+
│ 2 │ │
1040+
├──────────┤
1041+
│ 3 │
1042+
├──────────┤ Y part
1043+
│ 4 │
1044+
├──────────┤
1045+
│ 5 │ │
1046+
├──────────┤ │
1047+
│ 6 │ │
1048+
├──────────┤ │
1049+
│ 7 │ ▼
1050+
└──────────┴───────────
1051+
```
1052+
1053+
桶数组增大后,原来同一个桶的数据可以被分别移动到上半区和下半区。
1054+
9331055
## indirectkey 和 indirectvalue
9341056

9351057
在上面的代码中我们见过无数次的 indirectkey 和 indirectvalue。indirectkey 和 indirectvalue 在 map 里实际存储的是指针,会造成 GC 扫描时,扫描更多的对象。至于是否是 indirect,依然是由编译器来决定的,依据是:

0 commit comments

Comments
 (0)