Skip to content

Files

Latest commit

Jun 17, 2021
7c8d771 ยท Jun 17, 2021

History

History
1271 lines (1129 loc) ยท 82.4 KB

map.md

File metadata and controls

1271 lines (1129 loc) ยท 82.4 KB

map

          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                                                                                                                                                           
          โ”‚    hmap     โ”‚                                                                                                                                                                                                           
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                               
          โ”‚           count int            โ”‚           โ”‚               โ”‚                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                          โ”Œโ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                                                               
          โ”‚                                โ”‚           โ”‚               โ–ผ                     โ”‚                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           โ”‚    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”                  โ”‚                  โ”‚   tophash [bucketCnt]uint8    โ”‚    โ”‚    โ”‚   tophash [bucketCnt]uint8    โ”‚                                         
          โ”‚          flags uint8           โ”‚           โ”‚       โ–ฒ    โ”‚  0  โ”‚                  โ”‚                  โ”‚                               โ”‚    โ”‚    โ”‚                               โ”‚                                         
          โ”‚                                โ”‚           โ”‚       โ”‚    โ”‚     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           โ”‚       โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                     โ”‚   keys   โ”‚                    โ”‚    โ”‚    โ”‚   keys   โ”‚                    โ”‚                                         
          โ”‚            B uint8             โ”‚           โ”‚       โ”‚    โ”‚  1  โ”‚                                     โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                         
          โ”‚                                โ”‚           โ”‚       โ”‚    โ”‚     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚    โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           โ”‚       โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                  โ”‚                  โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                         
          โ”‚        noverflow uint16        โ”‚           โ”‚       โ”‚    โ”‚  2  โ”‚                  โ”‚                  โ”‚  values  โ”‚                    โ”‚    โ”‚    โ”‚  values  โ”‚                    โ”‚                                         
          โ”‚                                โ”‚           โ”‚       โ”‚    โ”‚     โ”‚                  โ”‚                  โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           โ”‚       โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                  โ”‚                  โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚    โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                         
          โ”‚          hash0 uint32          โ”‚           โ”‚       โ”‚    โ”‚  3  โ”‚                  โ”‚                  โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                         
          โ”‚                                โ”‚           โ”‚       โ”‚    โ”‚     โ”‚                  โ”‚                  โ”‚        overflow *bmap         โ”‚    โ”‚    โ”‚        overflow *bmap         โ”‚                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค           โ”‚       โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                  โ”‚                  โ”‚                               โ”‚โ”€โ”€โ”€โ”€โ”˜    โ”‚                               โ”‚                                         
          โ”‚     buckets unsafe.Pointer     โ”‚           โ”‚       โ”‚    โ”‚  4  โ”‚                  โ”‚                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                         
          โ”‚                                โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚    โ”‚     โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                                                                                                         
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                        โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                                   
          โ”‚   oldbuckets unsafe.Pointer    โ”‚                        โ”‚  5  โ”‚                                     โ”‚   tophash [bucketCnt]uint8    โ”‚                                                                                   
          โ”‚                                โ”‚                        โ”‚     โ”‚                                     โ”‚                               โ”‚                                                                                   
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค         size = 2 ^ B   โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                                                   
          โ”‚       nevacuate uintptr        โ”‚                        โ”‚  6  โ”‚                                     โ”‚   keys   โ”‚                    โ”‚                                                                                   
          โ”‚                                โ”‚                        โ”‚     โ”‚                                     โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                                                                   
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                   โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                     โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                                                                   
          โ”‚        extra *mapextra         โ”‚                   โ”‚    โ”‚  7  โ”‚                                     โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                                                                   
       โ”Œโ”€โ”€โ”‚                                โ”‚                   โ”‚    โ”‚     โ”‚                                     โ”‚  values  โ”‚                    โ”‚                                                                                   
       โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                   โ”‚    โ””โ”€โ”€โ”€โ”€โ”€โ”˜                                     โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                                                                   
       โ”‚                                                       โ”‚      ....                                      โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                                                                   
       โ”‚                                                       โ”‚                                                โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                                                                   
       โ”‚                                                       โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”€โ”                                     โ”‚        overflow *bmap         โ”‚                                                                                   
       โ”‚                                                       โ”‚    โ”‚ 61  โ”‚                                     โ”‚                               โ”‚                                                                                   
       โ”‚                                                       โ”‚    โ”‚     โ”‚                                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                                                   
       โ–ผ                                                       โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                               ............                                                                                              
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                โ”‚    โ”‚ 62  โ”‚                                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      
โ”‚  mapextra   โ”‚                                                โ”‚    โ”‚     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                          โ”Œโ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                         โ”Œโ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                      
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                 โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”ค                                     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚     overflow *[]*bmap      โ”‚                                 โ”‚    โ”‚ 63  โ”‚                                     โ”‚   tophash [bucketCnt]uint8    โ”‚    โ”‚    โ”‚   tophash [bucketCnt]uint8    โ”‚   โ”‚    โ”‚   tophash [bucketCnt]uint8    โ”‚
โ”‚                            โ”‚                                 โ–ผ    โ”‚     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                  โ”‚                               โ”‚    โ”‚    โ”‚                               โ”‚   โ”‚    โ”‚                               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                              โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”˜                  โ”‚                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”‚    โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚    oldoverflow *[]*bmap    โ”‚                                                               โ”‚                  โ”‚   keys   โ”‚                    โ”‚    โ”‚    โ”‚   keys   โ”‚                    โ”‚   โ”‚    โ”‚   keys   โ”‚                    โ”‚
โ”‚                            โ”‚                                                               โ”‚                  โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค   โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                               โ”‚                  โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚    โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚   โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚
โ”‚     nextoverflow *bmap     โ”‚                                                               โ”‚                  โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค   โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค
โ”‚                            โ”‚                                                               โ”‚                  โ”‚  values  โ”‚                    โ”‚    โ”‚    โ”‚  values  โ”‚                    โ”‚   โ”‚    โ”‚  values  โ”‚                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                               โ”‚                  โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค   โ”‚    โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค
                                                                                             โ”‚                  โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚    โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚   โ”‚    โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚
                                                                                             โ”‚                  โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค    โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค   โ”‚    โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค
                                                                                             โ”‚                  โ”‚        overflow *bmap         โ”‚    โ”‚    โ”‚        overflow *bmap         โ”‚   โ”‚    โ”‚        overflow *bmap         โ”‚
                                                                                             โ”‚                  โ”‚                               โ”‚โ”€โ”€โ”€โ”€โ”˜    โ”‚                               โ”‚โ”€โ”€โ”€โ”˜    โ”‚                               โ”‚
                                                                                             โ”‚                  โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                                             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚  bmap   โ”‚                                                                                                         
                                                                                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                                   
                                                                                                                โ”‚   tophash [bucketCnt]uint8    โ”‚                                                                                   
                                                                                                                โ”‚                               โ”‚                                                                                   
                                                                                                                โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                                                   
                                                                                                                โ”‚   keys   โ”‚                    โ”‚                                                                                   
                                                                                                                โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                                                                   
                                                                                                                โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                                                                   
                                                                                                                โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                                                                   
                                                                                                                โ”‚  values  โ”‚                    โ”‚                                                                                   
                                                                                                                โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”ดโ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ค                                                                                   
                                                                                                                โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚                                                                                   
                                                                                                                โ”œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ค                                                                                   
                                                                                                                โ”‚        overflow *bmap         โ”‚                                                                                   
                                                                                                                โ”‚                               โ”‚                                                                                   
                                                                                                                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                                                   

ๆ•ฐๆฎ็ป“ๆž„

const (
    // ไธ€ไธช bucket ๆœ€ๅคš่ƒฝๆ”พ็š„ๅ…ƒ็ด ๆ•ฐ
    bucketCntBits = 3
    bucketCnt     = 1 << bucketCntBits

    // load factor = 13/2
    loadFactorNum = 13
    loadFactorDen = 2

    // ่ถ…่ฟ‡่ฟ™ไธคไธช size ็š„ๅฏนๅบ”ๅฏน่ฑก๏ผŒไผš่ขซ่ฝฌไธบๆŒ‡้’ˆ
    maxKeySize   = 128
    maxValueSize = 128

    // data offset should be the size of the bmap struct, but needs to be
    // aligned correctly. For amd64p32 this means 64-bit alignment
    // even though pointers are 32 bit.
    dataOffset = unsafe.Offsetof(struct {
        b bmap
        v int64
    }{}.v)

    // tophash ้™คไบ†ๆ”พๆญฃๅธธ็š„้ซ˜ 8 ไฝ็š„ hash ๅ€ผ
    // ่ฟ˜ไผšๅœจ็ฉบ้—ฒใ€่ฟ็งปๆ—ถๅญ˜ๅ‚จไธ€ไบ›็‰นๅพ็š„็Šถๆ€ๅ€ผ
    // ๆ‰€ไปฅๅˆๆณ•็š„ tophash(ๆŒ‡่ฎก็ฎ—ๅ‡บๆฅ็š„้‚ฃ็ง)๏ผŒๆœ€ๅฐไนŸๅบ”่ฏฅๆ˜ฏ 4
    // ๅฐไบŽ 4 ็š„่กจ็คบ็š„้ƒฝๆ˜ฏๆˆ‘ไปฌ่‡ชๅทฑๅฎšไน‰็š„็Šถๆ€ๅ€ผ
    empty          = 0 // cell is empty
    evacuatedEmpty = 1 // cell is empty, bucket is evacuated.
    evacuatedX     = 2 // key/value is valid.  Entry has been evacuated to first half of larger table.
    evacuatedY     = 3 // same as above, but evacuated to second half of larger table.
    minTopHash     = 4 // minimum tophash for a normal filled cell.

    // flags
    iterator     = 1 // there may be an iterator using buckets
    oldIterator  = 2 // there may be an iterator using oldbuckets
    hashWriting  = 4 // a goroutine is writing to the map
    sameSizeGrow = 8 // the current map growth is to a new map of the same size

    // sentinel bucket ID for iterator checks
    noCheck = 1<<(8*sys.PtrSize) - 1
)

// A header for a Go map.
type hmap struct {
    count     int // map ไธญ็š„ๅ…ƒ็ด ไธชๆ•ฐ๏ผŒๅฟ…้กปๆ”พๅœจ struct ็š„็ฌฌไธ€ไธชไฝ็ฝฎ๏ผŒๅ› ไธบ ๅ†…็ฝฎ็š„ len ๅ‡ฝๆ•ฐไผšไปŽ่ฟ™้‡Œ่ฏปๅ–
    flags     uint8
    B         uint8  // log_2 of # of buckets (ๆœ€ๅคšๅฏไปฅๆ”พ loadFactor * 2^B ไธชๅ…ƒ็ด ๏ผŒๅ†ๅคšๅฐฑ่ฆ hashGrow ไบ†)
    noverflow uint16 // overflow ็š„ bucket ็š„่ฟ‘ไผผๆ•ฐ
    hash0     uint32 // hash seed

    buckets    unsafe.Pointer // 2^B ๅคงๅฐ็š„ๆ•ฐ็ป„๏ผŒๅฆ‚ๆžœ count == 0 ็š„่ฏ๏ผŒๅฏ่ƒฝๆ˜ฏ nil
    oldbuckets unsafe.Pointer // ไธ€ๅŠๅคงๅฐ็š„ไน‹ๅ‰็š„ bucket ๆ•ฐ็ป„๏ผŒๅชๆœ‰ๅœจ growing ่ฟ‡็จ‹ไธญๆ˜ฏ้ž nil
    nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

    extra *mapextra // ๅฝ“ key ๅ’Œ value ้ƒฝๅฏไปฅ inline ็š„ๆ—ถๅ€™๏ผŒๅฐฑไผš็”จ่ฟ™ไธชๅญ—ๆฎต
}

type mapextra struct {
    // ๅฆ‚ๆžœ key ๅ’Œ value ้ƒฝไธๅŒ…ๅซๆŒ‡้’ˆ๏ผŒๅนถไธ”ๅฏไปฅ่ขซ inline(<=128 ๅญ—่Š‚)
    // ไฝฟ็”จ extra ๆฅๅญ˜ๅ‚จ overflow bucket๏ผŒ่ฟ™ๆ ทๅฏไปฅ้ฟๅ… GC ๆ‰ซๆๆ•ดไธช map
    // ็„ถ่€Œ bmap.overflow ไนŸๆ˜ฏไธชๆŒ‡้’ˆใ€‚่ฟ™ๆ—ถๅ€™ๆˆ‘ไปฌๅช่ƒฝๆŠŠ่ฟ™ไบ› overflow ็š„ๆŒ‡้’ˆ
    // ้ƒฝๆ”พๅœจ hmap.extra.overflow ๅ’Œ hmap.extra.oldoverflow ไธญไบ†
    // overflow ๅŒ…ๅซ็š„ๆ˜ฏ hmap.buckets ็š„ overflow ็š„ bucket
    // oldoverflow ๅŒ…ๅซๆ‰ฉๅฎนๆ—ถ็š„ hmap.oldbuckets ็š„ overflow ็š„ bucket
    overflow    *[]*bmap
    oldoverflow *[]*bmap

    // ๆŒ‡ๅ‘็ฉบ้—ฒ็š„ overflow bucket ็š„ๆŒ‡้’ˆ
    nextOverflow *bmap
}

// bucket ๆœฌไฝ“
type bmap struct {
    // tophash ๆ˜ฏ hash ๅ€ผ็š„้ซ˜ 8 ไฝ
    tophash [bucketCnt]uint8
    // keys
    // values
    // overflow pointer
}

ๅˆๅง‹ๅŒ–

ๅฝขๅฆ‚:

make(map[k]v, hint)

็š„ไปฃ็ ๏ผŒๅœจ hint <= 8(bucketSize) ๆ—ถ๏ผŒไผš่ฐƒ็”จ makemap_small ๆฅ่ฟ›่กŒๅˆๅง‹ๅŒ–๏ผŒๅฆ‚ๆžœ hint > 8๏ผŒๅˆ™่ฐƒ็”จ makemapใ€‚

make(map[k]v) // ๆต‹่ฏ•ๆ—ถ๏ผŒๆŠŠ่ฟ™ไธชไฝœไธบไธ€ไธชๅ…จๅฑ€ๅ˜้‡ var a = make(map[int]int)

ไธๆไพ› hint ็š„ไปฃ็ ๏ผŒ็ผ–่ฏ‘ๅ™จๅง‹็ปˆไผš่ฐƒ็”จ makemap_small ๆฅๅˆๅง‹ๅŒ–ใ€‚

// make(map[k]v, hint)
// ๅฆ‚ๆžœ็ผ–่ฏ‘ๅ™จ่ฎคไธบ map ๅ’Œ็ฌฌไธ€ไธช bucket ๅฏไปฅ็›ดๆŽฅๅˆ›ๅปบๅœจๆ ˆไธŠ๏ผŒh ๅ’Œ bucket ๅฏ่ƒฝ้ƒฝๆ˜ฏ้ž็ฉบ
// h != nil๏ผŒๅฏไปฅ็›ดๆŽฅๅœจ h ๅ†…ๅˆ›ๅปบ map
// ๅฆ‚ๆžœ h.buckets != nil๏ผŒๅ…ถๆŒ‡ๅ‘็š„ bucket ๅฏไปฅไฝœไธบ็ฌฌไธ€ไธช bucket ๆฅไฝฟ็”จ
func makemap(t *maptype, hint int, h *hmap) *hmap {
    // ๅœจ 64 ไฝ็ณป็ปŸไธŠ hmap ็ป“ๆž„ไฝ“ๅคงๅฐไธบ 48 ๅญ—่Š‚
    // 32 ไฝ็ณป็ปŸไธŠๆ˜ฏ 28 ๅญ—่Š‚
    if sz := unsafe.Sizeof(hmap{}); sz != 8+5*sys.PtrSize {
        println("runtime: sizeof(hmap) =", sz, ", t.hmap.size =", t.hmap.size)
        throw("bad hmap size")
    }

    if hint < 0 || hint > int(maxSliceCap(t.bucket.size)) {
        hint = 0
    }

    // ๅˆๅง‹ๅŒ– hmap
    if h == nil {
        h = (*hmap)(newobject(t.hmap))
    }
    h.hash0 = fastrand()

    // ๆŒ‰็…งๆไพ›็š„ๅ…ƒ็ด ไธชๆ•ฐ๏ผŒๆ‰พไธ€ไธชๅฏไปฅๆ”พๅพ—ไธ‹่ฟ™ไนˆๅคšๅ…ƒ็ด ็š„ B ๅ€ผ
    B := uint8(0)
    for overLoadFactor(hint, B) {
        B++
    }
    h.B = B

    // ๅˆ†้…ๅˆๅง‹็š„ hash table
    // ๅฆ‚ๆžœ B == 0๏ผŒbuckets ๅญ—ๆฎตไผš็”ฑ mapassign ๆฅ lazily ๅˆ†้…
    // ๅ› ไธบๅฆ‚ๆžœ hint ๅพˆๅคง็š„่ฏ๏ผŒๅฏน่ฟ™้ƒจๅˆ†ๅ†…ๅญ˜ๅฝ’้›ถไผš่Šฑๆฏ”่พƒ้•ฟๆ—ถ้—ด
    if h.B != 0 {
        var nextOverflow *bmap
        h.buckets, nextOverflow = makeBucketArray(t, h.B)
        if nextOverflow != nil {
            h.extra = new(mapextra)
            h.extra.nextOverflow = nextOverflow
        }
    }

    return h
}

ๅฝ“็„ถ๏ผŒๅฎž้™…้€‰็”จๅ“ชไธชๅ‡ฝๆ•ฐไธๅช่ฆ็œ‹ hint๏ผŒ่ฟ˜่ฆ็œ‹้€ƒ้€ธๅˆ†ๆž็ป“ๆžœ๏ผŒๆฏ”ๅฆ‚ไธ‹้ข่ฟ™ๆฎตไปฃ็ ๏ผŒๅœจ็”Ÿๆˆ็š„ๆฑ‡็ผ–ไธญ๏ผŒไฝ ๆ˜ฏๆ‰พไธๅˆฐ makemap ็š„่ธชๅฝฑ็š„๏ผš

package main

func main() {
	var m = make(map[int]int, 4)
	m[1] = 1
}

็ผ–่ฏ‘ๅ™จ็กฎๅฎš make map ๅ‡ฝๆ•ฐ็š„ไฝ็ฝฎๅœจ๏ผšcmd/compile/internal/gc/walk.go:1192:

	case OMAKEMAP:
		t := n.Type
		hmapType := hmap(t)
		hint := n.Left

ๆœ‰ๅ…ด่ถฃ็š„ๅŒๅญฆๅฏไปฅ่‡ช่กŒๆŸฅ็œ‹~

ๅ…ƒ็ด ่ฎฟ้—ฎ

ไธป่ฆๆ˜ฏๅฏน key ่ฟ›่กŒ hash ่ฎก็ฎ—๏ผŒ่ฎก็ฎ—ๅŽ็”จ low bits ๅ’Œ้ซ˜ 8 ไฝ hash ๆ‰พๅˆฐๅฏนๅบ”็š„ไฝ็ฝฎ:

   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                          
   โ”‚  10010111   โ”‚ 000011110110110010001111001010100010010110010101010 โ”‚    01010    โ”‚                          
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                          
          โ–ฒ                                                                   โ–ฒ                                 
          โ”‚                                                                   โ”‚                                 
          โ”‚                                                                   โ”‚                   B = 5         
          โ”‚                                                                   โ”‚             bucketMask = 11111  
          โ”‚                                                                   โ”‚                                 
          โ”‚                                                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        
          โ”‚                                                            โ”‚  low bits   โ”‚ & โ”‚ bucketMask  โ”‚        
          โ”‚                                                            โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค        
          โ”‚                                                            โ”‚         01010 & 11111         โ”‚        
          โ”‚                                                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ–ผ                        
          โ”‚                                                                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              
          โ”‚                                                                  โ”‚    01010 = 12     โ”‚              
          โ”‚                                                                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜              
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
          โ”‚                                                                            โ”‚                        
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                     โ”‚                        
   โ”‚   tophash   โ”‚                                                                     โ”‚                        
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                   โ”‚                        
          โ”‚                              โ”‚ buckets โ”‚                                   โ–ผ                        
          โ”‚                              โ”œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”ดโ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”     
          โ”‚                              โ”‚ 0 โ”‚ 1 โ”‚ 2 โ”‚ 3 โ”‚ 4 โ”‚ 5 โ”‚ 6 โ”‚ 7 โ”‚ 8 โ”‚ 9 โ”‚10 โ”‚11 โ”‚ ...โ”‚29 โ”‚30 โ”‚31 โ”‚     
          โ”‚                              โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜     
          โ–ผ                                                                            โ”‚                        
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                                   โ”‚                        
โ”‚  10010111 = 151  โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                     โ”‚                        
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚                                                     โ”‚                        
                                 โ”‚                                                     โ”‚                        
                                 โ”‚                                                     โ”‚                        
                                 โ”‚                             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                        
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ”‚                                                
                                 โ”‚                             โ–ผ                                                
                                 โ”‚                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                         
                                 โ”‚                      โ”‚   bucket    โ”‚                                         
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                         
   โ”‚                             โ”‚                                    โ”‚                                         
   โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                 โ”‚                                    โ”‚                                         
   โ”‚ โ”‚ tophash โ”‚                 โ–ผ                                    โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚                                         
   โ”‚ โ”‚  124  โ”‚  33   โ”‚  41   โ”‚  151  โ”‚   1   โ”‚   0   โ”‚   0   โ”‚   0   โ”‚โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚                                         
   โ”‚ โ”‚    1    โ”‚                                                      โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚                                         
   โ”‚ โ”‚  124  โ”‚  412  โ”‚  423  โ”‚   5   โ”‚  14   โ”‚   0   โ”‚   0   โ”‚   0   โ”‚โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚                                         
   โ”‚ โ”‚ values  โ”‚                                                      โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”โ”‚                                         
   โ”‚ โ”‚  v0   โ”‚  v1   โ”‚  v2   โ”‚  v3   โ”‚  v4   โ”‚   0   โ”‚   0   โ”‚   0   โ”‚โ”‚                                         
   โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜โ”‚                                         
   โ”‚ โ”‚ overflow pointer โ”‚                                             โ”‚                                         
   โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                             โ”‚                                         
   โ”‚                                                                  โ”‚                                         
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                         

ๅฎž็ŽฐไธŠๆœ‰ mapaccess1๏ผŒmapaccess2๏ผŒmapaccessK ๅ‡ ไธชๆ–นๆณ•๏ผŒไฝ†ๅ‡ ไธชๆ–นๆณ•้ƒฝๅทฎไธๅคš๏ผŒๅชๅทฎๅˆซๅœจ่ฟ”ๅ›žๅ†…ๅฎนไธŠใ€‚mapaccess1 ๅ’Œ mapaccess2 ๅŒๆ—ถๆœ‰ 32 ไฝใ€64 ไฝๅ’Œ string ็ฑปๅž‹็š„ๅ˜็ง:

  1. mapaccess1_fast32, mapaccess1_fast64, mapaccess1_faststr
  2. mapaccess2_fast32, mapaccess2_fast64, mapaccess2_faststr

ๅ…ทไฝ“็”จๅ“ชไธ€ไธชๅ˜็งๅ‡ฝๆ•ฐๆ˜ฏ็”ฑ็ผ–่ฏ‘ๅ™จๅœจ็ผ–่ฏ‘ๆœŸ้€‰ๆ‹ฉ็š„๏ผŒ้€‰ๆ‹ฉไพๆฎๅฏไปฅๅ‚่€ƒๅŽ้ข็š„่ต‹ๅ€ผไธ€ๅฐ่Š‚ใ€‚

ๅ› ไธบ่ฟ™ไบ›ๅ‡ฝๆ•ฐๅฎž็ŽฐไธŠ้ƒฝๅคงๅŒๅฐๅผ‚๏ผŒๆˆ‘ไปฌๆŒ‘ไธ€ไธชๆฅ็œ‹็œ‹ mapaccess2:

func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool) {
    // map ไธบ็ฉบ๏ผŒๆˆ–่€…ๅ…ƒ็ด ๆ•ฐไธบ 0๏ผŒ็›ดๆŽฅ่ฟ”ๅ›žๆœชๆ‰พๅˆฐ
    if h == nil || h.count == 0 {
        return unsafe.Pointer(&zeroVal[0]), false
    }
    if h.flags&hashWriting != 0 {
        throw("concurrent map read and map write")
    }
    alg := t.key.alg
    // ไธๅŒ็ฑปๅž‹็š„ key๏ผŒๆ‰€็”จ็š„ hash ็ฎ—ๆณ•ๆ˜ฏไธไธ€ๆ ท็š„
    // ๅ…ทไฝ“ๅฏไปฅๅ‚่€ƒ algarray
    hash := alg.hash(key, uintptr(h.hash0))
    // ๅฆ‚ๆžœ B = 3๏ผŒ้‚ฃไนˆ็ป“ๆžœ็”จไบŒ่ฟ›ๅˆถ่กจ็คบๅฐฑๆ˜ฏ 111
    // ๅฆ‚ๆžœ B = 4๏ผŒ้‚ฃไนˆ็ป“ๆžœ็”จไบŒ่ฟ›ๅˆถ่กจ็คบๅฐฑๆ˜ฏ 1111
    m := bucketMask(h.B)
    // ๆŒ‰ไฝ &๏ผŒๅฏไปฅ select ๅ‡บๅฏนๅบ”็š„ bucket
    b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
    // ไผš็”จๅˆฐ h.oldbuckets ๆ—ถ๏ผŒ่ฏดๆ˜Ž map ๅ‘็”Ÿไบ†ๆ‰ฉๅฎน
    // ่ฟ™ๆ—ถๅ€™๏ผŒๆ–ฐ็š„ buckets ้‡Œๅฏ่ƒฝ่ฟ˜ๆฒกๆœ‰่€็š„ๅ†…ๅฎน
    // ๆ‰€ไปฅไธ€ๅฎš่ฆๅœจ่€็š„้‡Œ้ขๆ‰พ๏ผŒๅฆๅˆ™ๆœ‰ๅฏ่ƒฝๅ‘็”Ÿโ€œๆถˆๅคฑโ€็š„่ฏกๅผ‚็Žฐ่ฑก
    if c := h.oldbuckets; c != nil {
        if !h.sameSizeGrow() {
            // ่ฏดๆ˜Žไน‹ๅ‰ๅชๆœ‰ไธ€ๅŠ็š„ bucket๏ผŒ้œ€่ฆ้™ค 2
            m >>= 1
        }
        oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize)))
        if !evacuated(oldb) {
            b = oldb
        }
    }
    // tophash ๅ–ๅ…ถ้ซ˜ 8bit ็š„ๅ€ผ
    top := tophash(hash)
    for ; b != nil; b = b.overflow(t) {
        // ไธ€ไธช bucket ๅœจๅญ˜ๅ‚จๆปก 8 ไธชๅ…ƒ็ด ๅŽ๏ผŒๅฐฑๅ†ไนŸๆ”พไธไธ‹ไบ†
        // ่ฟ™ๆ—ถๅ€™ไผšๅˆ›ๅปบๆ–ฐ็š„ bucket
        // ๆŒ‚ๅœจๅŽŸๆฅ็š„ bucket ็š„ overflow ๆŒ‡้’ˆๆˆๅ‘˜ไธŠ
        for i := uintptr(0); i < bucketCnt; i++ {
            // ๅพช็Žฏๅฏนๆฏ” bucket ไธญ็š„ tophash ๆ•ฐ็ป„
            // ๅฆ‚ๆžœๆ‰พๅˆฐไบ†็›ธ็ญ‰็š„ tophash๏ผŒ้‚ฃ่ฏดๆ˜Žๅฐฑๆ˜ฏ่ฟ™ไธช bucket ไบ†
            if b.tophash[i] != top {
                continue
            }
            k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
            if t.indirectkey {
                k = *((*unsafe.Pointer)(k))
            }
            if alg.equal(key, k) {
                v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
                if t.indirectvalue {
                    v = *((*unsafe.Pointer)(v))
                }
                return v, true
            }
        }
    }

    // ๆ‰€ๆœ‰ bucket ้ƒฝๆฒกๆœ‰ๆ‰พๅˆฐ๏ผŒ่ฟ”ๅ›ž้›ถๅ€ผๅ’Œ false
    return unsafe.Pointer(&zeroVal[0]), false
}

ๆ˜พ็„ถ๏ผŒ่ฟ™ๅฐฑๆ˜ฏๆˆ‘ไปฌๅนณๅธธๅœจๅ†™ๅฆ‚ไธ‹ไปฃ็ ๆ—ถ:

v, ok := m[k]

ๆ‰€ไฝฟ็”จ็š„ๅบ•ๅฑ‚ๅ‡ฝๆ•ฐใ€‚

่ต‹ๅ€ผ

็ผ–่ฏ‘ๅ™จๅฆ‚ไฝ•้€‰ๆ‹ฉ assign ๅ‡ฝๆ•ฐ

mapassign ๆœ‰ๅ‡ ไธชๅ˜็ง๏ผŒๆ˜ฏ็”ฑ็ผ–่ฏ‘ๅ™จๅ†ณๅฎšๅ…ทไฝ“็”จๅ“ชไธ€ไธชๅ‡ฝๆ•ฐ็š„ใ€‚้€‰ๆ‹ฉไพๆฎ:

  1. key ็š„็ฑปๅž‹ๆ˜ฏๅฆๆ˜ฏ string
  2. ๅฆ‚ๆžœไธๆ˜ฏ string๏ผŒ้‚ฃไนˆๆ นๆฎ key ็š„็ฑปๅž‹ๅคงๅฐๅš้€‰ๆ‹ฉ

ๆต็จ‹ๅ›พ:

Loading
graph TD
Z[value size gte 128] --> |yes|G[mapassign]
Z --> |no| A[key is string]
A --> |yes|B[mapassign_faststr]
A --> |no|C[key size is 32]
C --> |yes|D[mapassign_fast32]
C --> |no|E[key size is 64]
E --> |yes|F[mapassign_fast64]
E --> |no|G[mapassign]

่ต‹ๅ€ผๆต็จ‹

ๅ‡ ไธชๅ‡ฝๆ•ฐ้•ฟๅพ—้ƒฝๅทฎไธๅคš๏ผŒๆˆ‘ไปฌ็œ‹ไธ€ไธ‹ mapassign ็š„้€ป่พ‘ๅฐฑ่กŒไบ†:

// ๅ’Œ mapaccess ๅ‡ฝๆ•ฐๅทฎไธๅคš๏ผŒไฝ†ๅœจๆฒกๆœ‰ๆ‰พๅˆฐ key ๆ—ถ๏ผŒไผšไธบ key ๅˆ†้…ไธ€ไธชๆ–ฐ็š„ๆงฝไฝ
func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
    if h == nil {
        // nil map ไธ่ƒฝ่ฟ›่กŒ่ต‹ๅ€ผๆ“ไฝœ
        panic(plainError("assignment to entry in nil map"))
    }
    if h.flags&hashWriting != 0 {
        throw("concurrent map writes")
    }

    // ่ฐƒ็”จๅฏนๅบ”็ฑปๅž‹็š„ hash ็ฎ—ๆณ•
    alg := t.key.alg
    hash := alg.hash(key, uintptr(h.hash0))

    // ่ฐƒ็”จ alg.hash ่ฎพ็ฝฎ hashWriting ็š„ flag๏ผŒๅ› ไธบ alg.hash ๅฏ่ƒฝไผš panic
    // ่ฟ™ๆ—ถๅ€™ๆˆ‘ไปฌๆฒกๆณ•ๅฎŒๆˆไธ€ๆฌกๅ†™ๆ“ไฝœ
    h.flags |= hashWriting

    if h.buckets == nil {
        // ๅˆ†้…็ฌฌไธ€ไธช buckt
        h.buckets = newobject(t.bucket) // newarray(t.bucket, 1)
    }

again:
    // ่ฎก็ฎ—ไฝŽ 8 ไฝ hash๏ผŒๆ นๆฎ่ฎก็ฎ—ๅ‡บ็š„ bucketMask ้€‰ๆ‹ฉๅฏนๅบ”็š„ bucket
    // mask : 1111111
    bucket := hash & bucketMask(h.B)
    if h.growing() {
        growWork(t, h, bucket)
    }
    // ่ฎก็ฎ—ๅ‡บๅญ˜ๅ‚จ็š„ bucket ็š„ๅ†…ๅญ˜ไฝ็ฝฎ
    // pos = start + bucketNumber * bucetsize
    // ่ฟ™้‡Œ็š„ๅ‘ฝๅไธๅคชๅฅฝ๏ผŒbucket ๅ…ถๅฎžๆ˜ฏ bucketNumber
    b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
    // ่ฎก็ฎ—้ซ˜ 8 ไฝ hash
    top := tophash(hash)

    var inserti *uint8
    var insertk unsafe.Pointer
    var val unsafe.Pointer
    for {
        for i := uintptr(0); i < bucketCnt; i++ {
            // ้ๅކ 8 ไธช bucket ไธญ็š„ๅ…ƒ็ด 
            // ่ฟ™้‡Œ็š„ bucketCnt ๆ˜ฏๅ…จๅฑ€ๅธธ้‡
            // ๅ…ถๅฎžๅซ bucketElemCnt ๆ›ดๅˆ้€‚
            if b.tophash[i] != top {
                // ๅœจ b.tophash[i] != top ็š„ๆƒ…ๅ†ตไธ‹
                // ็†่ฎบไธŠๆœ‰ๅฏ่ƒฝไผšๆ˜ฏไธ€ไธช็ฉบๆงฝไฝ
                // ไธ€่ˆฌๆƒ…ๅ†ตไธ‹ map ็š„ๆงฝไฝๅˆ†ๅธƒๆ˜ฏ่ฟ™ๆ ท็š„๏ผŒe ่กจ็คบ empty:
                // [h1][h2][h3][h4][h5][e][e][e]
                // ไฝ†ๅœจๆ‰ง่กŒ่ฟ‡ delete ๆ“ไฝœๆ—ถ๏ผŒๅฏ่ƒฝไผšๅ˜ๆˆ่ฟ™ๆ ท:
                // [h1][h2][e][e][h5][e][e][e]
                // ๆ‰€ไปฅๅฆ‚ๆžœๅ†ๆ’ๅ…ฅ็š„่ฏ๏ผŒไผšๅฐฝ้‡ๅพ€ๅ‰้ข็š„ไฝ็ฝฎๆ’
                // [h1][h2][e][e][h5][e][e][e]
                //          ^
                //          ^
                //       ่ฟ™ไธชไฝ็ฝฎ
                // ๆ‰€ไปฅๅœจๅพช็Žฏ็š„ๆ—ถๅ€™่ฟ˜่ฆ้กบไพฟๆŠŠๅ‰้ข็š„็ฉบไฝ็ฝฎๅ…ˆ่ฎฐไธ‹ๆฅ
                if b.tophash[i] == empty && inserti == nil {
                    // ๅฆ‚ๆžœ่ฟ™ไธชๆงฝไฝๆฒกๆœ‰่ขซๅ ๏ผŒ่ฏดๆ˜Žๅฏไปฅๅพ€่ฟ™้‡Œๅกž key ๅ’Œ value
                    inserti = &b.tophash[i] // tophash ็š„ๆ’ๅ…ฅไฝ็ฝฎ
                    insertk = add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
                    val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
                }
                continue
            }
            k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
            if t.indirectkey {
                k = *((*unsafe.Pointer)(k))
            }
            // ๅฆ‚ๆžœ็›ธๅŒ็š„ hash ไฝ็ฝฎ็š„ key ๅ’Œ่ฆๆ’ๅ…ฅ็š„ key ๅญ—้ขไธŠไธ็›ธ็ญ‰
            // ๅฆ‚ๆžœไธคไธช key ็š„้ฆ–ๅ…ซไฝๅŽๆœ€ๅŽๅ…ซไฝๅ“ˆๅธŒๅ€ผไธ€ๆ ท๏ผŒๅฐฑไผš่ฟ›่กŒๅ…ถๅ€ผๆฏ”่พƒ
            // ็ฎ—ๆ˜ฏไธ€็งๅ“ˆๅธŒ็ขฐๆ’žๅง
            if !alg.equal(key, k) {
                continue
            }
            // ๅฏนๅบ”็š„ไฝ็ฝฎๅทฒ็ปๆœ‰ key ไบ†๏ผŒ็›ดๆŽฅๆ›ดๆ–ฐๅฐฑ่กŒ
            if t.needkeyupdate {
                typedmemmove(t.key, k, key)
            }
            val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
            goto done
        }
        // bucket ็š„ 8 ไธชๆงฝๆฒกๆœ‰ๆปก่ถณๆกไปถ็š„่ƒฝๆ’ๅ…ฅๆˆ–่€…่ƒฝๆ›ดๆ–ฐ็š„๏ผŒๅŽป overflow ้‡Œ็ปง็ปญๆ‰พ
        ovf := b.overflow(t)
        // ๅฆ‚ๆžœ overflow ไธบ nil๏ผŒ่ฏดๆ˜Žๅˆฐไบ† overflow ้“พ่กจ็š„ๆœซ็ซฏไบ†
        if ovf == nil {
            break
        }
        // ่ต‹ๅ€ผไธบ้“พ่กจ็š„ไธ‹ไธ€ไธชๅ…ƒ็ด ๏ผŒ็ปง็ปญๅพช็Žฏ
        b = ovf
    }

    // ๆฒกๆœ‰ๆ‰พๅˆฐ key๏ผŒๅˆ†้…ๆ–ฐ็š„็ฉบ้—ด

    // ๅฆ‚ๆžœ่งฆๅ‘ไบ†ๆœ€ๅคง็š„ load factor๏ผŒๆˆ–่€…ๅทฒ็ปๆœ‰ๅคชๅคš overflow buckets
    // ๅนถไธ”่ฟ™ไธชๆ—ถๅˆปๆฒกๆœ‰ๅœจ่ฟ›่กŒ growing ็š„้€”ไธญ๏ผŒ้‚ฃไนˆๅฐฑๅผ€ๅง‹ growing
    if !h.growing() && (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
        hashGrow(t, h)
        // hashGrow ็š„ๆ—ถๅ€™ไผšๆŠŠๅฝ“ๅ‰็š„ bucket ๆ”พๅˆฐ oldbucket ้‡Œ
        // ไฝ†่ฟ˜ๆฒกๆœ‰ๅผ€ๅง‹ๅˆ†้…ๆ–ฐ็š„ bucket๏ผŒๆ‰€ไปฅ้œ€่ฆๅˆฐ again ้‡่ฏ•ไธ€ๆฌก
        // ้‡่ฏ•็š„ๆ—ถๅ€™ๅœจ growWork ้‡ŒไผšๆŠŠ่ฟ™ไธช key ็š„ bucket ไผ˜ๅ…ˆๅˆ†้…ๅฅฝ
        goto again // Growing the table invalidates everything, so try again
    }

    if inserti == nil {
        // ๅ‰้ขๅœจๆกถ้‡Œๆ‰พ็š„ๆ—ถๅ€™๏ผŒๆฒกๆœ‰ๆ‰พๅˆฐ่ƒฝๅกž่ฟ™ไธช tophash ็š„ไฝ็ฝฎ
        // ่ฏดๆ˜Žๅฝ“ๅ‰ๆ‰€ๆœ‰ buckets ้ƒฝๆ˜ฏๆปก็š„๏ผŒๅˆ†้…ไธ€ไธชๆ–ฐ็š„ bucket
        newb := h.newoverflow(t, b)
        inserti = &newb.tophash[0]
        insertk = add(unsafe.Pointer(newb), dataOffset)
        val = add(insertk, bucketCnt*uintptr(t.keysize))
    }

    // ๆŠŠๆ–ฐ็š„ key ๅ’Œ value ๅญ˜ๅ‚จๅˆฐๅบ”ๆ’ๅ…ฅ็š„ไฝ็ฝฎ
    if t.indirectkey {
        kmem := newobject(t.key)
        *(*unsafe.Pointer)(insertk) = kmem
        insertk = kmem
    }
    if t.indirectvalue {
        vmem := newobject(t.elem)
        *(*unsafe.Pointer)(val) = vmem
    }
    typedmemmove(t.key, insertk, key)
    *inserti = top
    h.count++

done:
    if h.flags&hashWriting == 0 {
        throw("concurrent map writes")
    }
    h.flags &^= hashWriting
    if t.indirectvalue {
        val = *((*unsafe.Pointer)(val))
    }
    return val
}

่ฟ™้‡Œๆœ‰ไปถๆฏ”่พƒๅฅ‡ๆ€ช็š„ไบ‹ๆƒ…๏ผŒmapassign ๅนถๆฒกๆœ‰ๆŠŠ็”จๆˆท m[k] = v ๆ—ถ็š„ v ๅ†™ๅ…ฅๅˆฐ map ็š„ value ๅŒบๅŸŸ๏ผŒ่€Œๆ˜ฏ็›ดๆŽฅ่ฟ”ๅ›žไบ†่ฟ™ไธชๅ€ผๆ‰€ๅบ”่ฏฅๅœจ็š„ๅ†…ๅญ˜ๅœฐๅ€ใ€‚้‚ฃไนˆๆŠŠ v ๆ‹ท่ดๅˆฐ่ฏฅๅ†…ๅญ˜ๅŒบๅŸŸ็š„ๆ“ไฝœๆ˜ฏๅœจๅ“ช้‡Œๅš็š„ๅ‘ข๏ผŸ

    var a = make(map[int]int, 7)
    for i := 0; i < 1000; i++ {
        a[i] = 99999
    }

็œ‹็œ‹็”Ÿๆˆ็š„ๆฑ‡็ผ–้ƒจๅˆ†:

    0x003f 00063 (m.go:9)    MOVQ    DX, (SP) // ็ฌฌไธ€ไธชๅ‚ๆ•ฐ
    0x0043 00067 (m.go:9)    MOVQ    AX, 8(SP) // ็ฌฌไบŒไธชๅ‚ๆ•ฐ
    0x0048 00072 (m.go:9)    MOVQ    CX, 16(SP) // ็ฌฌไธ‰ไธชๅ‚ๆ•ฐ
    0x004d 00077 (m.go:9)    PCDATA    $0, $1 // GC ็›ธๅ…ณ
    0x004d 00077 (m.go:9)    CALL    runtime.mapassign_fast64(SB) // ่ฐƒ็”จๅ‡ฝๆ•ฐ
    0x0052 00082 (m.go:9)    MOVQ    24(SP), AX // ่ฟ”ๅ›žๅ€ผ๏ผŒๅณ value ๅบ”่ฏฅๅญ˜ๆ”พ็š„ๅ†…ๅญ˜ๅœฐๅ€
    0x0057 00087 (m.go:9)    MOVQ    $99999, (AX) // ๆŠŠ 99999 ๆ”พๅ…ฅ่ฏฅๅœฐๅ€ไธญ

่ต‹ๅ€ผ็š„ๆœ€ๅŽไธ€ๆญฅๅฎž้™…ไธŠๆ˜ฏ็ผ–่ฏ‘ๅ™จ้ขๅค–็”Ÿๆˆ็š„ๆฑ‡็ผ–ๆŒ‡ไปคๆฅๅฎŒๆˆ็š„๏ผŒๅฏ่ง้  runtime ๆœ‰ไบ›ๅทฅไฝœๆ˜ฏๆฒกๆœ‰ๅšๅฎŒ็š„ใ€‚่ฟ™้‡Œๅ’Œ go ๅœจๅ‡ฝๆ•ฐ่ฐƒ็”จๆ—ถๆ’ๅ…ฅ prologue ๅ’Œ epilogue ๆ˜ฏ็ฑปไผผ็š„ใ€‚็ผ–่ฏ‘ๅ™จๅ’Œ runtime ้…ๅˆ๏ผŒๆ‰่ƒฝๅฎŒๆˆไธ€ไบ›ๅคๆ‚็š„ๅทฅไฝœใ€‚

ๅˆ ้™ค

func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
    if h == nil || h.count == 0 {
        return
    }
    if h.flags&hashWriting != 0 {
        throw("concurrent map writes")
    }

    alg := t.key.alg
    hash := alg.hash(key, uintptr(h.hash0))

    // ่ฐƒ็”จ alg.hash ่ฎพ็ฝฎ hashWriting ็š„ flag๏ผŒๅ› ไธบ alg.hash ๅฏ่ƒฝไผš panic
    // ่ฟ™ๆ—ถๅ€™ๆˆ‘ไปฌๆฒกๆณ•ๅฎŒๆˆไธ€ๆฌกๅ†™ๆ“ไฝœ
    h.flags |= hashWriting

    // ๆŒ‰ไฝŽ 8 ไฝ hash ๅ€ผ้€‰ๆ‹ฉ bucket
    bucket := hash & bucketMask(h.B)
    if h.growing() {
        growWork(t, h, bucket)
    }
    // ๆŒ‰ไธŠ้ข็ฎ—ๅ‡บ็š„ๆกถ็š„็ดขๅผ•๏ผŒๆ‰พๅˆฐ bucket ็š„ๅ†…ๅญ˜ๅœฐๅ€
    // ๅนถๅผบๅˆถ่ฝฌๆขไธบ้œ€่ฆ็š„ bmap ็ป“ๆž„
    b := (*bmap)(add(h.buckets, bucket*uintptr(t.bucketsize)))
    // ้ซ˜ 8 ไฝ hash ๅ€ผ
    top := tophash(hash)
search:
    for ; b != nil; b = b.overflow(t) {
        for i := uintptr(0); i < bucketCnt; i++ {
            // ๅ’ŒไธŠ้ข็š„ๅทฎไธๅคš๏ผŒ8 ไธชๆงฝไฝ๏ผŒๅˆ†ๅˆซๅฏนๆฏ” tophash
            // ๆฒกๆ‰พๅˆฐ็š„่ฏๅฐฑๅŽปๅค–ๅ›ด for ๅพช็Žฏ็š„ overflow ้“พ่กจไธญ็ปง็ปญๆŸฅๆ‰พ
            if b.tophash[i] != top {
                continue
            }

            // b.tophash[i] == top
            // ่ฎก็ฎ— k ๆ‰€ๅœจ็š„ๆงฝไฝ็š„ๅ†…ๅญ˜ๅœฐๅ€
            k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
            k2 := k
            // ๅฆ‚ๆžœ key > 128 ๅญ—่Š‚
            if t.indirectkey {
                k2 = *((*unsafe.Pointer)(k2))
            }

            // ๅฝ“้ซ˜ 8 ไฝๅ“ˆๅธŒๅ€ผ็›ธ็ญ‰ๆ—ถ๏ผŒ่ฟ˜้œ€่ฆๅฏนๅ…ทไฝ“ๅ€ผ่ฟ›่กŒๆฏ”่พƒ
            // ไปฅ้ฟๅ…ๅ“ˆๅธŒๅ†ฒ็ชๆ—ถๅ€ผ่ฆ†็›–
            if !alg.equal(key, k2) {
                continue
            }

            // ๅฆ‚ๆžœ key ไธญๆ˜ฏๆŒ‡้’ˆ๏ผŒ้‚ฃไนˆๆธ…็ฉบ key ็š„ๅ†…ๅฎน
            if t.indirectkey {
                *(*unsafe.Pointer)(k) = nil
            } else if t.key.kind&kindNoPointers == 0 {
                memclrHasPointers(k, t.key.size)
            }

            // ่ฎก็ฎ— value ๆ‰€ๅœจ็š„ๅ†…ๅญ˜ๅœฐๅ€
            v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
            // ๅ’ŒไธŠ้ข key ็š„้€ป่พ‘ๅทฎไธๅคš
            if t.indirectvalue {
                *(*unsafe.Pointer)(v) = nil
            } else if t.elem.kind&kindNoPointers == 0 {
                memclrHasPointers(v, t.elem.size)
            } else {
                memclrNoHeapPointers(v, t.elem.size)
            }
            // ่ฎพ็ฝฎ tophash[i] = 0
            b.tophash[i] = empty
            // hmap ็š„ๅคงๅฐ่ฎกๆ•ฐ -1
            h.count--
            break search
        }
    }

    if h.flags&hashWriting == 0 {
        throw("concurrent map writes")
    }
    h.flags &^= hashWriting
}

็ผฉๅฎน

Go ็š„ map ๆ˜ฏไธไผš็ผฉๅฎน็š„๏ผŒ้™ค้žไฝ ๆŠŠๆ•ดไธช map ๅˆ ๆމ:

golang/go#20135

ๆ‰ฉๅฎน

ๆ‰ฉๅฎน่งฆๅ‘ๅœจ mapassign ไธญ๏ผŒๆˆ‘ไปฌไน‹ๅ‰ๆณจ้‡Š่ฟ‡ไบ†๏ผŒไธป่ฆๆ˜ฏไธค็‚น:

  1. ๆ˜ฏไธๆ˜ฏๅทฒ็ปๅˆฐไบ† load factor ็š„ไธด็•Œ็‚น๏ผŒๅณๅ…ƒ็ด ไธชๆ•ฐ >= ๆกถไธชๆ•ฐ * 6.5๏ผŒ่ฟ™ๆ—ถๅ€™่ฏดๆ˜Žๅคง้ƒจๅˆ†็š„ๆกถๅฏ่ƒฝ้ƒฝๅฟซๆปกไบ†๏ผŒๅฆ‚ๆžœๆ’ๅ…ฅๆ–ฐๅ…ƒ็ด ๏ผŒๆœ‰ๅคงๆฆ‚็އ้œ€่ฆๆŒ‚ๅœจ overflow ็š„ๆกถไธŠใ€‚
  2. overflow ็š„ๆกถๆ˜ฏไธๆ˜ฏๅคชๅคšไบ†๏ผŒๅฝ“ bucket ๆ€ปๆ•ฐ < 2 ^ 15 ๆ—ถ๏ผŒๅฆ‚ๆžœ overflow ็š„ bucket ๆ€ปๆ•ฐ >= bucket ็š„ๆ€ปๆ•ฐ๏ผŒ้‚ฃไนˆๆˆ‘ไปฌ่ฎคไธบ overflow ็š„ๆกถๅคชๅคšไบ†ใ€‚ๅฝ“ bucket ๆ€ปๆ•ฐ >= 2 ^ 15 ๆ—ถ๏ผŒ้‚ฃๆˆ‘ไปฌ็›ดๆŽฅๅ’Œ 2 ^ 15 ๆฏ”่พƒ๏ผŒoverflow ็š„ bucket >= 2 ^ 15 ๆ—ถ๏ผŒๅณ่ฎคไธบๆบขๅ‡บๆกถๅคชๅคšไบ†ใ€‚ไธบๅ•ฅไผšๅฏผ่‡ด่ฟ™็งๆƒ…ๅ†ตๅ‘ข๏ผŸๆ˜ฏๅ› ไธบๆˆ‘ไปฌๅฏน map ไธ€่พนๆ’ๅ…ฅ๏ผŒไธ€่พนๅˆ ้™ค๏ผŒไผšๅฏผ่‡ดๅ…ถไธญๅพˆๅคšๆกถๅ‡บ็Žฐ็ฉบๆดž๏ผŒ่ฟ™ๆ ทไฝฟๅพ— bucket ไฝฟ็”จ็އไธ้ซ˜๏ผŒๅ€ผๅญ˜ๅ‚จๅพ—ๆฏ”่พƒ็จ€็–ใ€‚ๅœจๆŸฅๆ‰พๆ—ถๆ•ˆ็އไผšไธ‹้™ใ€‚

ไธค็งๆƒ…ๅ†ตๅฎ˜ๆ–น้‡‡็”จไบ†ไธๅŒ็š„่งฃๅ†ณๆ–นๆณ•:

  • ้’ˆๅฏน 1๏ผŒๅฐ† B + 1๏ผŒ่ฟ›่€Œ hmap ็š„ bucket ๆ•ฐ็ป„ๆ‰ฉๅฎนไธ€ๅ€๏ผ›
  • ้’ˆๅฏน 2๏ผŒ้€š่ฟ‡็งปๅŠจ bucket ๅ†…ๅฎน๏ผŒไฝฟๅ…ถๅ€พๅ‘ไบŽ็ดงๅฏ†ๆŽ’ๅˆ—ไปŽ่€Œๆ้ซ˜ bucket ๅˆฉ็”จ็އใ€‚

ๅฎž้™…ไธŠ่ฟ™้‡Œ่ฟ˜ๆœ‰ไธ€็ง้บป็ƒฆ็š„ๆƒ…ๅ†ต๏ผŒๅฆ‚ๆžœ map ไธญๆœ‰ๅคง้‡็š„ๅ“ˆๅธŒๅ†ฒ็ช็š„่ฏ๏ผŒไนŸไผšๅฏผ่‡ด่ฝๅ…ฅ 2 ไธญ็š„ๅˆคๆ–ญ๏ผŒ่ฟ™ๆ—ถๅ€™ๅฏน bucket ็š„ๅ†…ๅฎน่ฟ›่กŒ็งปๅŠจๅ…ถๅฎžๆฒกไป€ไนˆๆ„ไน‰๏ผŒๅ่€Œๆ˜ฏ็บฏ็ฒน็š„ๆ— ็”จๅŠŸ๏ผŒๆ‰€ไปฅ็†่ฎบไธŠๅญ˜ๅœจๅฏน Go ็š„ map ่ฟ›่กŒ hash ็ขฐๆ’žๆ”ปๅ‡ป็š„ๅฏ่ƒฝๆ€งใ€‚

ไฝ† Go ็š„ๆฏไธ€ไธช map ้ƒฝไผšๅœจๅˆๅง‹ๅŒ–้˜ถๆฎต็š„ makemap ๆ—ถๅฎšไธ€ไธช้šๆœบ็š„ hash seed๏ผŒๆ‰€ไปฅ่ฆๆž„้€ ่ฟ™็งๅ†ฒ็ชๆ˜ฏๆฒก้‚ฃไนˆๅฎนๆ˜“็š„ใ€‚

็œ‹็œ‹ hashGrow ็š„ๅ…ทไฝ“ๆต็จ‹:

func hashGrow(t *maptype, h *hmap) {
    // ๅฆ‚ๆžœๅทฒ็ป่ถ…่ฟ‡ไบ† load factor ็š„้˜ˆๅ€ผ๏ผŒ้‚ฃไนˆ้œ€่ฆๅฏน map ่ฟ›่กŒๆ‰ฉๅฎน๏ผŒๅณ B = B + 1๏ผŒbucket ๆ€ปๆ•ฐไผšๅ˜ไธบๅŽŸๆฅ็š„ไบŒๅ€
    // ๅฆ‚ๆžœ่ฟ˜ๆฒกๅˆฐ้˜ˆๅ€ผ๏ผŒ้‚ฃไนˆๅช้œ€่ฆไฟๆŒ็›ธๅŒๆ•ฐ้‡็š„ bucket๏ผŒๆจชๅ‘ๆ‹ๅนณๅฐฑ่กŒไบ†

    bigger := uint8(1)
    if !overLoadFactor(h.count+1, h.B) {
        bigger = 0
        h.flags |= sameSizeGrow
    }
    oldbuckets := h.buckets
    newbuckets, nextOverflow := makeBucketArray(t, h.B+bigger, nil)

    flags := h.flags &^ (iterator | oldIterator)
    if h.flags&iterator != 0 {
        flags |= oldIterator
    }

    // ๆไบคๆ‰ฉๅฎน็ป“ๆžœ
    h.B += bigger
    h.flags = flags
    h.oldbuckets = oldbuckets
    h.buckets = newbuckets
    h.nevacuate = 0
    h.noverflow = 0

    if h.extra != nil && h.extra.overflow != nil {
        // ๆŠŠๅฝ“ๅ‰็š„ overflow ่ต‹ๅ€ผ็ป™ oldoverflow
        if h.extra.oldoverflow != nil {
            throw("oldoverflow is not nil")
        }
        h.extra.oldoverflow = h.extra.overflow
        h.extra.overflow = nil
    }
    if nextOverflow != nil {
        if h.extra == nil {
            h.extra = new(mapextra)
        }
        h.extra.nextOverflow = nextOverflow
    }

    // ๅฎž้™…็š„ๅ“ˆๅธŒ่กจๅ…ƒ็ด ็š„ๆ‹ท่ดๅทฅไฝœๆ˜ฏๅœจ growWork ๅ’Œ evacuate ไธญๅขž้‡ๆ…ขๆ…ขๅœฐ่ฟ›่กŒ็š„
}
// makeBucketArray ไธบ map buckets ๅˆๅง‹ๅŒ–ๅบ•ๅฑ‚ๆ•ฐ็ป„
// 1<<b ๆ˜ฏ้œ€่ฆๅˆ†้…็š„ๆœ€ๅฐๆ•ฐ้‡ buckets
// dirtyalloc ่ฆไนˆๆ˜ฏ nil๏ผŒ่ฆไนˆๅฐฑๆ˜ฏไน‹ๅ‰็”ฑ makeBucketArray ไฝฟ็”จๅŒๆ ท็š„ t ๅ’Œ b ๅ‚ๆ•ฐ
// ๅˆ†้…็š„ๆ•ฐ็ป„
// ๅฆ‚ๆžœ dirtyalloc ๆ˜ฏ nil๏ผŒ้‚ฃไนˆๅฐฑไผšๅˆ†้…ไธ€ไธชๆ–ฐๆ•ฐ็ป„๏ผŒๅฆๅˆ™ไผšๆธ…็ฉบๆމๅŽŸๆฅ็š„ dirtyalloc
// ็„ถๅŽ้‡็”จ่ฟ™้ƒจๅˆ†ๅ†…ๅญ˜ไฝœไธบๆ–ฐ็š„ๅบ•ๅฑ‚ๆ•ฐ็ป„
func makeBucketArray(t *maptype, b uint8, dirtyalloc unsafe.Pointer) (buckets unsafe.Pointer, nextOverflow *bmap) {
    // base = 1 << b
    base := bucketShift(b)
    nbuckets := base
    // ๅฏนไบŽๆฏ”่พƒๅฐ็š„ b ๆฅ่ฏด๏ผŒไธๅคชๅฏ่ƒฝๆœ‰ overflow buckets
    // ่ฟ™้‡Œ็œๆމไธ€ไบ›่ฎก็ฎ—ๆถˆ่€—
    if b >= 4 {
        // Add on the estimated number of overflow buckets
        // required to insert the median number of elements
        // used with this value of b.
        nbuckets += bucketShift(b - 4)
        sz := t.bucket.size * nbuckets
        up := roundupsize(sz)
        if up != sz {
            nbuckets = up / t.bucket.size
        }
    }

    if dirtyalloc == nil {
        buckets = newarray(t.bucket, int(nbuckets))
    } else {
        // dirtyalloc ไน‹ๅ‰ๅฐฑๆ˜ฏ็”จไธŠ้ข็š„ newarray(t.bucket, int(nbuckets))
        // ็”Ÿๆˆ็š„๏ผŒๆ‰€ไปฅๆ˜ฏ้ž็ฉบ
        buckets = dirtyalloc
        size := t.bucket.size * nbuckets
        if t.bucket.kind&kindNoPointers == 0 {
            memclrHasPointers(buckets, size)
        } else {
            memclrNoHeapPointers(buckets, size)
        }
    }

    if base != nbuckets {
        // ๆˆ‘ไปฌ้ข„ๅˆ†้…ไบ†ไธ€ไบ› overflow buckets
        // ไธบไบ†่ฎฉ่ฟฝ่ธช่ฟ™ไบ› overflow buckets ็š„ๆˆๆœฌๆœ€ไฝŽ
        // ๆˆ‘ไปฌ่ฟ™้‡Œ็บฆๅฎš๏ผŒๅฆ‚ๆžœ้ข„ๅˆ†้…็š„ overflow bucket ็š„ overflow ๆŒ‡้’ˆๆ˜ฏ nil
        // ้‚ฃไนˆ there are more available by bumping the pointer.
        // ๆˆ‘ไปฌ้œ€่ฆไธ€ไธชๅฎ‰ๅ…จ็š„้ž็ฉบๆŒ‡้’ˆๆฅไฝœไธบ last overflow bucket๏ผŒ็›ดๆŽฅ็”จ buckets ๅฐฑ่กŒไบ†
        nextOverflow = (*bmap)(add(buckets, base*uintptr(t.bucketsize)))
        last := (*bmap)(add(buckets, (nbuckets-1)*uintptr(t.bucketsize)))
        last.setoverflow(t, (*bmap)(buckets))
    }
    return buckets, nextOverflow
}
func growWork(t *maptype, h *hmap, bucket uintptr) {
    // ็กฎไฟๆˆ‘ไปฌ็งปๅŠจ็š„ oldbucket ๅฏนๅบ”็š„ๆ˜ฏๆˆ‘ไปฌ้ฉฌไธŠๅฐฑ่ฆ็”จๅˆฐ็š„้‚ฃไธ€ไธช
    evacuate(t, h, bucket&h.oldbucketmask())

    // ๅฆ‚ๆžœ่ฟ˜ๅœจ growing ็Šถๆ€๏ผŒๅ†ๅคš็งปๅŠจไธ€ไธช oldbucket
    if h.growing() {
        evacuate(t, h, h.nevacuate)
    }
}
func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
    b := (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
    newbit := h.noldbuckets()
    if !evacuated(b) {
        // TODO: reuse overflow buckets instead of using new ones, if there
        // is no iterator using the old buckets.  (If !oldIterator.)

        // xy ๅŒ…ๅซ็š„ๆ˜ฏ็งปๅŠจ็š„็›ฎๆ ‡
        // x ่กจ็คบๆ–ฐ bucket ๆ•ฐ็ป„็š„ๅ‰(low)ๅŠ้ƒจๅˆ†
        // y ่กจ็คบๆ–ฐ bucket ๆ•ฐ็ป„็š„ๅŽ(high)ๅŠ้ƒจๅˆ†
        var xy [2]evacDst
        x := &xy[0]
        x.b = (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize)))
        x.k = add(unsafe.Pointer(x.b), dataOffset)
        x.v = add(x.k, bucketCnt*uintptr(t.keysize))

        if !h.sameSizeGrow() {
            // ๅฆ‚ๆžœ map ๅคงๅฐ(hmap.B)ๅขžๅคงไบ†๏ผŒ้‚ฃไนˆๆˆ‘ไปฌๅช่ฎก็ฎ— y
            // ๅฆๅˆ™ GC ๅฏ่ƒฝไผš็œ‹ๅˆฐๆŸๅ็š„ๆŒ‡้’ˆ
            y := &xy[1]
            y.b = (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize)))
            y.k = add(unsafe.Pointer(y.b), dataOffset)
            y.v = add(y.k, bucketCnt*uintptr(t.keysize))
        }

        for ; b != nil; b = b.overflow(t) {
            k := add(unsafe.Pointer(b), dataOffset)
            v := add(k, bucketCnt*uintptr(t.keysize))
            for i := 0; i < bucketCnt; i, k, v = i+1, add(k, uintptr(t.keysize)), add(v, uintptr(t.valuesize)) {
                top := b.tophash[i]
                if top == empty {
                    b.tophash[i] = evacuatedEmpty
                    continue
                }
                if top < minTopHash {
                    throw("bad map state")
                }
                k2 := k
                if t.indirectkey {
                    k2 = *((*unsafe.Pointer)(k2))
                }
                var useY uint8
                if !h.sameSizeGrow() {
                    // ่ฎก็ฎ—ๅ“ˆๅธŒ๏ผŒไปฅๅˆคๆ–ญๆˆ‘ไปฌ็š„ๆ•ฐๆฎ่ฆ่ฝฌ็งปๅˆฐๅ“ชไธ€้ƒจๅˆ†็š„ bucket
                    // ๅฏ่ƒฝๆ˜ฏ x ้ƒจๅˆ†๏ผŒไนŸๅฏ่ƒฝๆ˜ฏ y ้ƒจๅˆ†
                    hash := t.key.alg.hash(k2, uintptr(h.hash0))
                    if h.flags&iterator != 0 && !t.reflexivekey && !t.key.alg.equal(k2, k2) {
                        // ไธบไป€ไนˆ่ฆๅŠ  reflexivekey ็š„ๅˆคๆ–ญ๏ผŒๅฏไปฅๅ‚่€ƒ่ฟ™้‡Œ:
                        // https://go-review.googlesource.com/c/go/+/1480
                        // key != key๏ผŒๅชๆœ‰ๅœจ float ๆ•ฐ็š„ NaN ๆ—ถไผšๅ‡บ็Žฐ
                        // ๆฏ”ๅฆ‚:
                        // n1 := math.NaN()
                        // n2 := math.NaN()
                        // fmt.Println(n1, n2)
                        // fmt.Println(n1 == n2)
                        // ่ฟ™็งๆƒ…ๅ†ตไธ‹ n1 ๅ’Œ n2 ็š„ๅ“ˆๅธŒๅ€ผไนŸๅฎŒๅ…จไธไธ€ๆ ท
                        // ่ฟ™้‡Œๅฎ˜ๆ–น่กจ็คบ่ฟ™็งๆƒ…ๅ†ตๆ˜ฏไธๅฏๅค็Žฐ็š„
                        // ้œ€่ฆๅœจ iterators ๅ‚ไธŽ็š„ๆƒ…ๅ†ตไธ‹ๆ‰่ƒฝๅค็Žฐ
                        // ไฝ†ๆ˜ฏๅฏนไบŽ่ฟ™็ง key ๆˆ‘ไปฌไนŸๅฏไปฅ้šๆ„ๅฏนๅ…ถ็›ฎๆ ‡่ฟ›่กŒๅ‘้…
                        // ๅŒๆ—ถ tophash ๅฏนไบŽ NaN ไนŸๆฒกๅ•ฅๆ„ไน‰
                        // ่ฟ˜ๆ˜ฏๆŒ‰ๆญฃๅธธ็š„ๆƒ…ๅ†ตไธ‹็ฎ—ไธ€ไธช้šๆœบ็š„ tophash
                        // ็„ถๅŽๅ…ฌๅนณๅœฐๆŠŠ่ฟ™ไบ› key ๅนณๅ‡ๅˆ†ๅธƒๅˆฐๅ„ bucket ๅฐฑๅฅฝ
                        useY = top & 1 // ่ฎฉ่ฟ™ไธช key 50% ๆฆ‚็އๅŽป Y ๅŠๅŒบ
                        top = tophash(hash)
                    } else {
                        // ่ฟ™้‡Œๅ†™็š„ๆฏ”่พƒ trick
                        // ๆฏ”ๅฆ‚ๅฝ“ๅ‰ๆœ‰ 8 ไธชๆกถ
                        // ้‚ฃไนˆๅฆ‚ๆžœ hash & 8 != 0
                        // ้‚ฃไนˆ่ฏดๆ˜Ž่ฟ™ไธชๅ…ƒ็ด ็š„ hash ่ฟ™็งๅฝขๅผ
                        // xxx1xxx
                        // ่€Œๆ‰ฉๅฎนๅŽ็š„ bucketMask ๆ˜ฏ
                        //    1111
                        // ๆ‰€ไปฅๅฎž้™…ไธŠ่ฟ™ไธชๅฐฑๆ˜ฏ
                        // xxx1xxx & 1000 > 0
                        // ่ฏดๆ˜Ž่ฟ™ไธชๅ…ƒ็ด ๅœจๆ‰ฉๅฎนๅŽไธ€ๅฎšไผšๅŽปไธ‹ๅŠๅŒบ๏ผŒๅณY้ƒจๅˆ†
                        // ๆ‰€ไปฅๅฐฑๆ˜ฏ useY ไบ†
                        if hash&newbit != 0 {
                            useY = 1
                        }
                    }
                }

                if evacuatedX+1 != evacuatedY {
                    throw("bad evacuatedN")
                }

                b.tophash[i] = evacuatedX + useY // evacuatedX + 1 == evacuatedY
                dst := &xy[useY]                 // ็งปๅŠจ็›ฎๆ ‡

                if dst.i == bucketCnt {
                    dst.b = h.newoverflow(t, dst.b)
                    dst.i = 0
                    dst.k = add(unsafe.Pointer(dst.b), dataOffset)
                    dst.v = add(dst.k, bucketCnt*uintptr(t.keysize))
                }
                dst.b.tophash[dst.i&(bucketCnt-1)] = top // mask dst.i as an optimization, to avoid a bounds check
                if t.indirectkey {
                    *(*unsafe.Pointer)(dst.k) = k2 // ๆ‹ท่ดๆŒ‡้’ˆ
                } else {
                    typedmemmove(t.key, dst.k, k) // ๆ‹ท่ดๅ€ผ
                }
                if t.indirectvalue {
                    *(*unsafe.Pointer)(dst.v) = *(*unsafe.Pointer)(v)
                } else {
                    typedmemmove(t.elem, dst.v, v)
                }
                dst.i++
                // These updates might push these pointers past the end of the
                // key or value arrays.  That's ok, as we have the overflow pointer
                // at the end of the bucket to protect against pointing past the
                // end of the bucket.
                dst.k = add(dst.k, uintptr(t.keysize))
                dst.v = add(dst.v, uintptr(t.valuesize))
            }
        }
        // Unlink the overflow buckets & clear key/value to help GC.
        if h.flags&oldIterator == 0 && t.bucket.kind&kindNoPointers == 0 {
            b := add(h.oldbuckets, oldbucket*uintptr(t.bucketsize))
            // Preserve b.tophash because the evacuation
            // state is maintained there.
            ptr := add(b, dataOffset)
            n := uintptr(t.bucketsize) - dataOffset
            memclrHasPointers(ptr, n)
        }
    }

    if oldbucket == h.nevacuate {
        advanceEvacuationMark(h, t, newbit)
    }
}
func advanceEvacuationMark(h *hmap, t *maptype, newbit uintptr) {
    h.nevacuate++
    // Experiments suggest that 1024 is overkill by at least an order of magnitude.
    // Put it in there as a safeguard anyway, to ensure O(1) behavior.
    stop := h.nevacuate + 1024
    if stop > newbit {
        stop = newbit
    }
    for h.nevacuate != stop && bucketEvacuated(t, h, h.nevacuate) {
        h.nevacuate++
    }
    if h.nevacuate == newbit { // newbit == # of oldbuckets
        // ๅคงๅฐๅขž้•ฟๅ…จ้ƒจ็ป“ๆŸใ€‚้‡Šๆ”พ่€็š„ bucket array
        h.oldbuckets = nil
        // ๅŒๆ ทๅฏไปฅไธขๅผƒ่€็š„ overflow buckets
        // ๅฆ‚ๆžœๅฎƒไปฌ่ฟ˜่ขซ่ฟญไปฃๅ™จๆ‰€ๅผ•็”จ็š„่ฏ
        // ่ฟญไปฃๅ™จไผšๆŒๆœ‰ไธ€ไปฝๆŒ‡ๅ‘ slice ็š„ๆŒ‡้’ˆ
        if h.extra != nil {
            h.extra.oldoverflow = nil
        }
        h.flags &^= sameSizeGrow
    }
}

ไปฃ็ ็œ‹็€ๆฏ”่พƒๆŠฝ่ฑก๏ผŒๅ†่กฅไธคไธชๅ›พ:

  • sameSizeGrow
                                                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                  โ”‚    0     โ”‚    1     โ”‚    2     โ”‚    3     โ”‚    4     โ”‚    5     โ”‚    6     โ”‚    7     โ”‚
                                                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              โ”‚  tophash: 10   โ”‚                                                            
                             โ”‚     empty      โ”‚              โ”‚ lowbits: 1001  โ”‚                                                            
                             โ”‚                โ”‚โ—€โ”€โ”€โ”€โ”€โ”€โ”       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                             โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚     empty      โ”‚                                                            
                             โ”‚     empty      โ”‚      โ”‚       โ”‚                โ”‚                                                            
                             โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                             โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚     empty      โ”‚                                                            
                             โ”‚     empty      โ”‚      โ”‚       โ”‚                โ”‚                                                            
                    โ”‚        โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚  tophash: 23   โ”‚                                                            
                    โ”‚        โ”‚     empty      โ”‚      โ”‚       โ”‚ lowbits: 0001  โ”‚                                                            
                    โ”‚        โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚     empty      โ”‚                                                            
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚        โ”‚     empty      โ”‚      โ”‚       โ”‚                โ”‚                                                            
โ”‚  before  โ”‚        โ”‚        โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚  tophash: 100  โ”‚                                                            
                    โ”‚        โ”‚     empty      โ”‚      โ”‚       โ”‚ lowbits: 0001  โ”‚                                                            
                    โ”‚        โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚     empty      โ”‚                                                            
                    โ”‚        โ”‚  tophash: 15   โ”‚      โ”‚       โ”‚                โ”‚                                                            
                    โ”‚        โ”‚ lowbits: 0001  โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค      โ”‚       โ”‚     empty      โ”‚                                                            
                    โ”‚        โ”‚     empty      โ”‚      โ”‚       โ”‚                โ”‚                                                            
                    โ”‚        โ”‚                โ”‚      โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜                                                            
                    โ”‚        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ overflow โ”‚                                                                  
                    โ”‚                                        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                                  
                    โ”‚                                                                                                                      
                    โ”‚                                                                                                                      
                    โ”‚                                                                                                                      
                    โ”‚                                                                                                                      
                    โ”‚                                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                            
                    โ”‚                                        โ”‚  tophash: 10   โ”‚                                                            
                    โ”‚                                        โ”‚ lowbits: 1001  โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚  tophash: 23   โ”‚                                                            
                    โ”‚                                        โ”‚ lowbits: 0001  โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚  tophash: 100  โ”‚                                                            
                    โ”‚                                        โ”‚ lowbits: 0001  โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚  tophash: 15   โ”‚                                                            
                    โ”‚                                        โ”‚ lowbits: 0001  โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚                                        โ”‚     empty      โ”‚                                                            
โ”‚  after   โ”‚        โ”‚                                        โ”‚                โ”‚                                                            
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚     empty      โ”‚                                                            
                    โ”‚                                        โ”‚                โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚     empty      โ”‚                                                            
                    โ”‚                                        โ”‚                โ”‚                                                            
                    โ”‚                                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                                                            
                    โ”‚                                        โ”‚     empty      โ”‚                                                            
                    โ”‚                                        โ”‚                โ”‚                                                            
                    โ”‚                             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚                             โ”‚    0     โ”‚    1     โ”‚    2     โ”‚    3     โ”‚    4     โ”‚    5     โ”‚    6     โ”‚    7     โ”‚
                    โ”‚                             โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ”‚                             โ”‚โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€         X part           โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚
                    โ”‚                             โ”‚                                                                                       โ”‚
                    โ–ผ                             โ”‚                                                                                       โ”‚
                                                  โ”‚                                                                                       โ”‚
                                                  โ”‚                                                                                       โ”‚
                                                  โ”‚                                                                                       โ”‚

sameSizeGrow ไน‹ๅŽ๏ผŒๆ•ฐๆฎๆŽ’ๅˆ—ๆ›ด็ดงๅ‡‘ใ€‚

  • biggerSizeGrow
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  
โ”‚    0     โ”‚                                              โ”‚    0     โ”‚     โ–ฒ       
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
โ”‚    1     โ”‚  tophash: 10  โ”‚   tophash:23   โ”‚      โ”Œโ”€โ”€โ”€โ”€โ”€โ–ถโ”‚    1     โ”‚     โ”‚       
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค lowbits: 1001 โ”‚ low bits: 0001 โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
โ”‚    2     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ”‚    2     โ”‚     โ”‚       
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค             
โ”‚    3     โ”‚       โ”‚                                      โ”‚    3     โ”‚             
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     X part  
โ”‚    4     โ”‚       โ”‚                                      โ”‚    4     โ”‚             
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค             
โ”‚    5     โ”‚       โ”‚                                      โ”‚    5     โ”‚     โ”‚       
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
โ”‚    6     โ”‚       โ”‚                                      โ”‚    6     โ”‚     โ”‚       
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
โ”‚    7     โ”‚       โ”‚                                      โ”‚    7     โ”‚     โ–ผ       
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  
                   โ”‚                                      โ”‚    8     โ”‚     โ–ฒ       
                   โ”‚                                      โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚    9     โ”‚     โ”‚       
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
                                                          โ”‚    10    โ”‚     โ”‚       
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค             
                                                          โ”‚    11    โ”‚             
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     Y part  
                                                          โ”‚    12    โ”‚             
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค             
                                                          โ”‚    13    โ”‚     โ”‚       
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
                                                          โ”‚    14    โ”‚     โ”‚       
                                                          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค     โ”‚       
                                                          โ”‚    15    โ”‚     โ–ผ       
                                                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  

ๆกถๆ•ฐ็ป„ๅขžๅคงๅŽ๏ผŒๅŽŸๆฅๅŒไธ€ไธชๆกถ็š„ๆ•ฐๆฎๅฏไปฅ่ขซๅˆ†ๅˆซ็งปๅŠจๅˆฐไธŠๅŠๅŒบๅ’Œไธ‹ๅŠๅŒบใ€‚

indirectkey ๅ’Œ indirectvalue

ๅœจไธŠ้ข็š„ไปฃ็ ไธญๆˆ‘ไปฌ่ง่ฟ‡ๆ— ๆ•ฐๆฌก็š„ indirectkey ๅ’Œ indirectvalueใ€‚indirectkey ๅ’Œ indirectvalue ๅœจ map ้‡Œๅฎž้™…ๅญ˜ๅ‚จ็š„ๆ˜ฏๆŒ‡้’ˆ๏ผŒไผš้€ ๆˆ GC ๆ‰ซๆๆ—ถ๏ผŒๆ‰ซๆๆ›ดๅคš็š„ๅฏน่ฑกใ€‚่‡ณไบŽๆ˜ฏๅฆๆ˜ฏ indirect๏ผŒไพ็„ถๆ˜ฏ็”ฑ็ผ–่ฏ‘ๅ™จๆฅๅ†ณๅฎš็š„๏ผŒไพๆฎๆ˜ฏ:

  1. key > 128 ๅญ—่Š‚ๆ—ถ๏ผŒindirectkey = true
  2. value > 128 ๅญ—่Š‚ๆ—ถ๏ผŒindirectvalue = true

ๆˆ‘ไปฌๅฏไปฅ็”จ lldb ๆฅ่ฟ›่กŒ็ฎ€ๅ•้ชŒ่ฏ:

package main

import "fmt"

func main() {
    type P struct {
        Age [16]int
    }
    var a = map[P]int{}
    a[P{}] = 1
    fmt.Println(a)
}

ๅœจ lldb ไธญๅฏไปฅ็œ‹ๅˆฐ indirectkey ไธบ falseใ€‚

(lldb) b mapassign
(lldb) p *t
(runtime.maptype) *t = {
  typ = {
    size = 0x0000000000000008
    ptrdata = 0x0000000000000008
    hash = 2678392653
    tflag = 2
    align = 8
    fieldalign = 8
    kind = 53
    alg = 0x0000000001137020
    gcdata = 0x00000000010cf298
    str = 26128
    ptrToThis = 0
  }
  key = 0x00000000010a77a0
  elem = 0x000000000109d180
  bucket = 0x00000000010aea00
  hmap = 0x00000000010b4da0
  keysize = 128  =======> 128 ๅญ—่Š‚
  indirectkey = false =====> false
  valuesize = 8
  indirectvalue = false
  bucketsize = 1104
  reflexivekey = true
  needkeyupdate = false
}

็ป™ P ๅŠ ไธ€ไธชๅญ—่Š‚:

package main

import "fmt"

func main() {
    type P struct {
        Age  [16]int
        Male bool
    }
    var a = map[P]int{}
    a[P{}] = 1
    fmt.Println(a)
}

indirectkey ๅ˜ๆˆไบ† true:

(lldb) p *t
(runtime.maptype) *t = {
  typ = {
    size = 0x0000000000000008
    ptrdata = 0x0000000000000008
    hash = 2678392653
    tflag = 2
    align = 8
    fieldalign = 8
    kind = 53
    alg = 0x0000000001137020
    gcdata = 0x00000000010cf3b8
    str = 26176
    ptrToThis = 0
  }
  key = 0x00000000010a92c0
  elem = 0x000000000109d280
  bucket = 0x00000000010aeb20
  hmap = 0x00000000010b4ec0
  keysize = 8 ======> ๅ˜ๆˆไบ† 8 ๅญ—่Š‚็š„ๆŒ‡้’ˆ
  indirectkey = true ======> ๅ˜ๆˆไบ† true
  valuesize = 8
  indirectvalue = false
  bucketsize = 144
  reflexivekey = true
  needkeyupdate = false
}

indirectvalue ไนŸๆ˜ฏๅฎŒๅ…จไธ€ๆ ท็š„๏ผŒ่ถ…่ฟ‡ 128 ๅญ—่Š‚(ไธๅซ)ๆ—ถ๏ผŒไผš่ขซ่ต‹ๅ€ผไธบ true๏ผŒๅนถ้€€ๅŒ–ไธบๆŒ‡้’ˆใ€‚

overflow ๅค„็†

ๆ€่ทฏ๏ผŒไปŽ nextOverflow ไธญๆ‹ฟ overflow bucket๏ผŒๅฆ‚ๆžœๆ‹ฟๅˆฐ๏ผŒๅฐฑๆ”พ่ฟ› hmap.extra.overflow ๆ•ฐ็ป„๏ผŒๅนถ่ฎฉ bmap ็š„ overflow pointer ๆŒ‡ๅ‘่ฟ™ไธช bucketใ€‚

ๅฆ‚ๆžœๆฒกๆ‰พๅˆฐ๏ผŒ้‚ฃๅฐฑ new ไธ€ไธชใ€‚

func (h *hmap) newoverflow(t *maptype, b *bmap) *bmap {
    var ovf *bmap
    if h.extra != nil && h.extra.nextOverflow != nil {
        // We have preallocated overflow buckets available.
        // See makeBucketArray for more details.
        ovf = h.extra.nextOverflow
        if ovf.overflow(t) == nil {
            // We're not at the end of the preallocated overflow buckets. Bump the pointer.
            h.extra.nextOverflow = (*bmap)(add(unsafe.Pointer(ovf), uintptr(t.bucketsize)))
        } else {
            // This is the last preallocated overflow bucket.
            // Reset the overflow pointer on this bucket,
            // which was set to a non-nil sentinel value.
            ovf.setoverflow(t, nil)
            h.extra.nextOverflow = nil
        }
    } else {
        ovf = (*bmap)(newobject(t.bucket))
    }
    h.incrnoverflow()
    if t.bucket.kind&kindNoPointers != 0 {
        h.createOverflow()
        *h.extra.overflow = append(*h.extra.overflow, ovf)
    }
    b.setoverflow(t, ovf)
    return ovf
}
func (h *hmap) createOverflow() {
    if h.extra == nil {
        h.extra = new(mapextra)
    }
    if h.extra.overflow == nil {
        h.extra.overflow = new([]*bmap)
    }
}
// incrnoverflow increments h.noverflow.
// noverflow counts the number of overflow buckets.
// This is used to trigger same-size map growth.
// See also tooManyOverflowBuckets.
// To keep hmap small, noverflow is a uint16.
// When there are few buckets, noverflow is an exact count.
// When there are many buckets, noverflow is an approximate count.
func (h *hmap) incrnoverflow() {
    // We trigger same-size map growth if there are
    // as many overflow buckets as buckets.
    // We need to be able to count to 1<<h.B.
    if h.B < 16 {
        h.noverflow++
        return
    }
    // Increment with probability 1/(1<<(h.B-15)).
    // When we reach 1<<15 - 1, we will have approximately
    // as many overflow buckets as buckets.
    mask := uint32(1)<<(h.B-15) - 1
    // Example: if h.B == 18, then mask == 7,
    // and fastrand & 7 == 0 with probability 1/8.
    if fastrand()&mask == 0 {
        h.noverflow++
    }
}