github.com/haraldrudell/parl@v0.4.176/pmaps/go-map-size.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pmaps 7 8 import ( 9 "unsafe" 10 11 "github.com/haraldrudell/parl/perrors" 12 ) 13 14 const ( 15 hmapFakeSizeInBytes = 10 // sizeof(int) is max 8, then there are two more uint8 16 hmapBOffset = int(unsafe.Sizeof(int(0))) + 1 17 ) 18 19 // GoMapSize returns the current size of the bucket array of Go map m 20 // - size is 0 for a nil map 21 // - size is 1 for an unallocated hash-table — rare case 22 // - otherwise size is a power of 2 23 // 24 // About Go map: 25 // - Go map is a hash map 26 // - a hash table is a space-time trade-off compared to array access 27 // - size is how many slots m’s hash table currently has 28 // - size may grow or shrink as m is modified 29 // - a mapping of the hash value-space is used for hash-table array access 30 // - each map slot contains a linked list of key-value pairs 31 // - more slots is faster closing in on O(1) complexity, fewer slots saves memory 32 // - Load factor is number of hash-table entries including collisions divided by 33 // hash table size 34 // 35 // Source code: 36 // - the map source code part of the runtime package is available online: 37 // - — https://go.googlesource.com/go/+/refs/heads/master/src/runtime/map.go 38 // - runtime source is typically installed on a computer that has Go: 39 // - — module directory: …libexec/src, package directory: runtime 40 // - — on macOS homebrew similar to: …/homebrew/Cellar/go/1.20.2/libexec/src 41 func GoMapSize[K comparable, V any](m map[K]V) (size uint64) { 42 43 if m == nil { 44 return // nil map return 45 } 46 47 // hmapp is a pointer to runtime.hmap struct 48 // - hmap begins with an int which is count of elements in map 4/8/bytes 49 // - then there is uint8 which is flags 50 // - then there is uint8 B wich is 2log(hash-table size) 51 var hmapp = *(**[hmapFakeSizeInBytes]uint8)(unsafe.Pointer(&m)) 52 53 // B is log2(hash-table size), uint8: 0…255 54 // - 2^255 ≈ 5e76, 1 GiB ≈ 1e9 55 var B = (*hmapp)[hmapBOffset] 56 if B > 63 { // B will not fit uint64 57 panic(perrors.ErrorfPF("hash table size corrupt: 2^%d", B)) 58 } 59 60 size = uint64(1) << B // size = 2^B 61 62 return 63 }