@@ -759,14 +759,106 @@ func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {
759759
760760我们可以用 lldb 来进行简单验证:
761761
762- ```
762+ ``` go
763+ package main
764+
765+ import " fmt"
766+
767+ func main () {
768+ type P struct {
769+ Age [17 ]int
770+ }
771+ var a = map [P]int {}
772+ a[P{}] = 1
773+ fmt.Println (a)
774+ }
775+
776+
763777```
764778
779+ 在 lldb 中可以看到 indirectkey 为 false。
780+
781+ ``` shell
782+ (lldb) b mapassign
783+ (lldb) p * t
784+ (runtime.maptype) * t = {
785+ typ = {
786+ size = 0x0000000000000008
787+ ptrdata = 0x0000000000000008
788+ hash = 2678392653
789+ tflag = 2
790+ align = 8
791+ fieldalign = 8
792+ kind = 53
793+ alg = 0x0000000001137020
794+ gcdata = 0x00000000010cf298
795+ str = 26128
796+ ptrToThis = 0
797+ }
798+ key = 0x00000000010a77a0
799+ elem = 0x000000000109d180
800+ bucket = 0x00000000010aea00
801+ hmap = 0x00000000010b4da0
802+ keysize = 128 =======> 128 字节
803+ indirectkey = false =====> false
804+ valuesize = 8
805+ indirectvalue = false
806+ bucketsize = 1104
807+ reflexivekey = true
808+ needkeyupdate = false
809+ }
765810```
811+
812+ 给 P 加一个字节:
813+
814+ ``` go
815+ package main
816+
817+ import " fmt"
818+
819+ func main () {
820+ type P struct {
821+ Age [16 ]int
822+ Male bool
823+ }
824+ var a = map [P]int {}
825+ a[P{}] = 1
826+ fmt.Println (a)
827+ }
766828```
767829
768- ## 其它
830+ indirectkey 变成了 true:
831+
832+ ``` shell
833+ (lldb) p * t
834+ (runtime.maptype) * t = {
835+ typ = {
836+ size = 0x0000000000000008
837+ ptrdata = 0x0000000000000008
838+ hash = 2678392653
839+ tflag = 2
840+ align = 8
841+ fieldalign = 8
842+ kind = 53
843+ alg = 0x0000000001137020
844+ gcdata = 0x00000000010cf3b8
845+ str = 26176
846+ ptrToThis = 0
847+ }
848+ key = 0x00000000010a92c0
849+ elem = 0x000000000109d280
850+ bucket = 0x00000000010aeb20
851+ hmap = 0x00000000010b4ec0
852+ keysize = 8
853+ indirectkey = true
854+ valuesize = 8
855+ indirectvalue = false
856+ bucketsize = 144
857+ reflexivekey = true
858+ needkeyupdate = false
859+ }
860+ ```
769861
770- 针对 32 位、64 位 和 string 类型的 map 元素的访问、赋值、删除、扩容,Go 内部有都有对应的优化函数,比如 mapaccess1 对应有 mapaccess1_fast64,mapaccess1_fast32,mapaccess1_faststr。mapassign 对应有 mapassign_fast64,mapassign_fast32 和 mapassign_faststr 。
862+ indirectvalue 也是完全一样的,超过 128 字节(不含)时,会被赋值为 true,并退化为指针 。
771863
772- 但这些优化函数长得都差不多,不知为何官方没有用脚本来做这些优化函数的生成工作。可见有时候 Go team 的复制粘贴功力也是蛮强的。
864+ ## 总结
0 commit comments