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  }