@@ -650,7 +650,7 @@ search:
650
650
1 . 是不是已经到了 load factor 的临界点,即元素个数 >= 桶个数 * 6.5,这时候说明大部分的桶可能都快满了,如果插入新元素,有大概率需要挂在 overflow 的桶上。
651
651
2 . overflow 的桶是不是太多了,当 bucket 总数 < 2 ^ 15 时,如果 overflow 的 bucket 总数 >= bucket 的总数,那么我们认为 overflow 的桶太多了。当 bucket 总数 >= 2 ^ 15 时,那我们直接和 2 ^ 15 比较,overflow 的 bucket >= 2 ^ 15 时,即认为溢出桶太多了。为啥会导致这种情况呢?是因为我们对 map 一边插入,一边删除,会导致其中很多桶出现空洞,这样使得 bucket 使用率不高,值存储得比较稀疏。在查找时效率会下降。
652
652
653
- 两种情况官方采用了不同的解决方法:
653
+ 两种情况官方采用了不同的解决方法:
654
654
655
655
* 针对 1,将 B + 1,进而 hmap 的 bucket 数组扩容一倍;
656
656
* 针对 2,通过移动 bucket 内容,使其倾向于紧密排列从而提高 bucket 利用率。
@@ -930,6 +930,128 @@ func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {
930
930
}
931
931
```
932
932
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
+
933
1055
## indirectkey 和 indirectvalue
934
1056
935
1057
在上面的代码中我们见过无数次的 indirectkey 和 indirectvalue。indirectkey 和 indirectvalue 在 map 里实际存储的是指针,会造成 GC 扫描时,扫描更多的对象。至于是否是 indirect,依然是由编译器来决定的,依据是:
0 commit comments