github.com/xgzlucario/GigaCache@v0.0.0-20240508025442-54204e9c8a6b/utils.go (about)

     1  package cache
     2  
     3  import (
     4  	"math/bits"
     5  	"sync/atomic"
     6  	"time"
     7  	"unsafe"
     8  )
     9  
    10  var (
    11  	// now nano time
    12  	nanosec atomic.Int64
    13  	sec     atomic.Uint32
    14  )
    15  
    16  //go:linkname FastRand runtime.fastrand
    17  func FastRand() uint32
    18  
    19  //go:linkname FastRand64 runtime.fastrand64
    20  func FastRand64() uint64
    21  
    22  type stringStruct struct {
    23  	str unsafe.Pointer
    24  	len int
    25  }
    26  
    27  //go:noescape
    28  //go:linkname memhash runtime.memhash
    29  func memhash(p unsafe.Pointer, h, s uintptr) uintptr
    30  
    31  func init() {
    32  	now := time.Now()
    33  	nanosec.Store(now.UnixNano())
    34  	sec.Store(uint32(now.Unix()))
    35  
    36  	go func() {
    37  		ticker := time.NewTicker(time.Millisecond)
    38  		for t := range ticker.C {
    39  			nanosec.Store(t.UnixNano())
    40  			sec.Store(uint32(t.Unix()))
    41  		}
    42  	}()
    43  }
    44  
    45  // GetNanoSec returns the current nano time.
    46  func GetNanoSec() int64 {
    47  	return nanosec.Load()
    48  }
    49  
    50  // GetSec returns the current unix time.
    51  func GetSec() uint32 {
    52  	return sec.Load()
    53  }
    54  
    55  type HashFn func(string) uint64
    56  
    57  // MemHash is the hash function used by go map, it utilizes available hardware instructions
    58  // (behaves as aes hash if aes instruction is available).
    59  // NOTE: The hash seed changes for every process. So, this cannot be used as a persistent hash.
    60  func MemHash(str string) uint64 {
    61  	ss := (*stringStruct)(unsafe.Pointer(&str))
    62  	return uint64(memhash(ss.str, 0, uintptr(ss.len)))
    63  }
    64  
    65  func s2b(str *string) []byte {
    66  	strHeader := (*[2]uintptr)(unsafe.Pointer(str))
    67  	byteSliceHeader := [3]uintptr{
    68  		strHeader[0], strHeader[1], strHeader[1],
    69  	}
    70  	return *(*[]byte)(unsafe.Pointer(&byteSliceHeader))
    71  }
    72  
    73  func b2s(b []byte) string {
    74  	return *(*string)(unsafe.Pointer(&b))
    75  }
    76  
    77  // SizeUvarint
    78  // See https://go-review.googlesource.com/c/go/+/572196/1/src/encoding/binary/varint.go#174
    79  func SizeUvarint(x uint64) int {
    80  	return int(9*uint32(bits.Len64(x))+64) / 64
    81  }