1. package main
    2. import (
    3. "fmt"
    4. "math/rand"
    5. "time"
    6. )
    7. var LFUInitRefCount uint8 = 5
    8. var LFUMaxRefCount uint8 = 255
    9. var LFUMaxAccessTs uint16 = 65535
    10. var LFUMaxRandNumber uint16 = 65535
    11. type LFUValueInfo struct {
    12. refCount uint8 // 引用计数
    13. lastAccessTs uint16 // 最近一次访问时间
    14. value interface{} // 数据
    15. }
    16. type LFUInfo struct {
    17. samples int // 抽样数量
    18. eleLimit int // 容器元素数量限制
    19. incFactor int // 引用计数增长因子,概率性增长,引用计数、增长因子越大,引用计数增长越慢
    20. decFactor int // 引用计数缩减因子,以分钟为单位,引用计数多少分钟减1
    21. mp map[interface{}]*LFUValueInfo
    22. }
    23. func (lfu *LFUInfo) Get(key interface{}) (value interface{}, ok bool) {
    24. data, ok := lfu.mp[key]
    25. if ok == false {
    26. return
    27. }
    28. lfu.updateValueInfo(data)
    29. return data.value, ok
    30. }
    31. func (lfu *LFUInfo) Set(key, value interface{}) {
    32. if _, ok := lfu.mp[key]; !ok {
    33. lfu.mp[key] = lfu.newLFUValueInfo()
    34. }
    35. data, _ := lfu.mp[key]
    36. data.value = value
    37. lfu.updateValueInfo(data)
    38. if len(lfu.mp) > lfu.eleLimit {
    39. lfu.adjustElements()
    40. }
    41. }
    42. func (lfu *LFUInfo) newLFUValueInfo() *LFUValueInfo {
    43. return &LFUValueInfo{refCount: LFUInitRefCount, lastAccessTs: lfu.getCurrentTsInMinutes()}
    44. }
    45. func (lfu *LFUInfo) updateValueInfo(data *LFUValueInfo) {
    46. if data == nil {
    47. return
    48. }
    49. // 根据增长因子计算引用计数
    50. lfu.incRefCount(data)
    51. // 根据衰减因子计算引用计数
    52. lfu.decRefCount(data)
    53. // 更新访问时间戳
    54. data.lastAccessTs = lfu.getCurrentTsInMinutes()
    55. }
    56. func (lfu *LFUInfo) incRefCount(data *LFUValueInfo) {
    57. if data.refCount == LFUMaxRefCount {
    58. return
    59. }
    60. baseCount := 0
    61. if data.refCount > LFUInitRefCount {
    62. baseCount = int(data.refCount - LFUInitRefCount)
    63. }
    64. p := float64(1.0) / float64(baseCount*lfu.incFactor+1)
    65. r := lfu.randIncRate()
    66. if r < p {
    67. data.refCount++
    68. }
    69. }
    70. func (lfu *LFUInfo) randIncRate() float64 {
    71. randValue := rand.Intn(int(LFUMaxRefCount))
    72. return float64(randValue) / float64(LFUMaxRefCount)
    73. }
    74. func (lfu *LFUInfo) decRefCount(data *LFUValueInfo) {
    75. if data.refCount == 0 {
    76. return
    77. }
    78. decValue := uint16(0)
    79. if lfu.decFactor > 0 {
    80. decValue = lfu.getRefCountDecValue(data.lastAccessTs) / uint16(lfu.decFactor)
    81. }
    82. if uint16(data.refCount) > decValue {
    83. data.refCount = data.refCount - uint8(decValue)
    84. } else {
    85. data.refCount = 0
    86. }
    87. }
    88. func (lfu *LFUInfo) getRefCountDecValue(lastMinutes uint16) uint16 {
    89. nowMinutes := lfu.getCurrentTsInMinutes()
    90. if nowMinutes > lastMinutes {
    91. return nowMinutes - lastMinutes
    92. } else {
    93. return LFUMaxAccessTs + nowMinutes - lastMinutes
    94. }
    95. }
    96. func (lfu *LFUInfo) getCurrentTsInMinutes() uint16 {
    97. return uint16(time.Now().Unix() / 60 % int64(LFUMaxAccessTs))
    98. }
    99. // 删除抽样数量中,引用次数最小的一个
    100. func (lfu *LFUInfo) adjustElements() {
    101. count := 0
    102. var delKey interface{}
    103. minCount := uint8(LFUMaxRefCount)
    104. for key, value := range lfu.mp {
    105. if count >= lfu.samples {
    106. break
    107. }
    108. if value.refCount <= minCount {
    109. minCount = value.refCount
    110. delKey = key
    111. }
    112. count++
    113. }
    114. fmt.Println(delKey)
    115. delete(lfu.mp, delKey)
    116. }
    117. func NewLFUInfo(inc, dec, sample, limit int) *LFUInfo {
    118. return &LFUInfo{
    119. samples: sample,
    120. eleLimit: limit,
    121. incFactor: inc,
    122. decFactor: dec,
    123. mp: make(map[interface{}]*LFUValueInfo),
    124. }
    125. }
    126. func main() {
    127. lfu := NewLFUInfo(10, 1, 10, 10000)
    128. for uli := 0; uli < 10001; uli++ {
    129. lfu.Set(uli, 10000+uli)
    130. }
    131. }

    代码来自 https://studygolang.com/topics/12462