You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

222 lines
4.0 KiB

  1. package lru
  2. import (
  3. "math/rand"
  4. "testing"
  5. )
  6. func BenchmarkLRU_Rand(b *testing.B) {
  7. l, err := New(8192)
  8. if err != nil {
  9. b.Fatalf("err: %v", err)
  10. }
  11. trace := make([]int64, b.N*2)
  12. for i := 0; i < b.N*2; i++ {
  13. trace[i] = rand.Int63() % 32768
  14. }
  15. b.ResetTimer()
  16. var hit, miss int
  17. for i := 0; i < 2*b.N; i++ {
  18. if i%2 == 0 {
  19. l.Add(trace[i], trace[i])
  20. } else {
  21. _, ok := l.Get(trace[i])
  22. if ok {
  23. hit++
  24. } else {
  25. miss++
  26. }
  27. }
  28. }
  29. b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(miss))
  30. }
  31. func BenchmarkLRU_Freq(b *testing.B) {
  32. l, err := New(8192)
  33. if err != nil {
  34. b.Fatalf("err: %v", err)
  35. }
  36. trace := make([]int64, b.N*2)
  37. for i := 0; i < b.N*2; i++ {
  38. if i%2 == 0 {
  39. trace[i] = rand.Int63() % 16384
  40. } else {
  41. trace[i] = rand.Int63() % 32768
  42. }
  43. }
  44. b.ResetTimer()
  45. for i := 0; i < b.N; i++ {
  46. l.Add(trace[i], trace[i])
  47. }
  48. var hit, miss int
  49. for i := 0; i < b.N; i++ {
  50. _, ok := l.Get(trace[i])
  51. if ok {
  52. hit++
  53. } else {
  54. miss++
  55. }
  56. }
  57. b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(miss))
  58. }
  59. func TestLRU(t *testing.T) {
  60. evictCounter := 0
  61. onEvicted := func(k interface{}, v interface{}) {
  62. if k != v {
  63. t.Fatalf("Evict values not equal (%v!=%v)", k, v)
  64. }
  65. evictCounter++
  66. }
  67. l, err := NewWithEvict(128, onEvicted)
  68. if err != nil {
  69. t.Fatalf("err: %v", err)
  70. }
  71. for i := 0; i < 256; i++ {
  72. l.Add(i, i)
  73. }
  74. if l.Len() != 128 {
  75. t.Fatalf("bad len: %v", l.Len())
  76. }
  77. if evictCounter != 128 {
  78. t.Fatalf("bad evict count: %v", evictCounter)
  79. }
  80. for i, k := range l.Keys() {
  81. if v, ok := l.Get(k); !ok || v != k || v != i+128 {
  82. t.Fatalf("bad key: %v", k)
  83. }
  84. }
  85. for i := 0; i < 128; i++ {
  86. _, ok := l.Get(i)
  87. if ok {
  88. t.Fatalf("should be evicted")
  89. }
  90. }
  91. for i := 128; i < 256; i++ {
  92. _, ok := l.Get(i)
  93. if !ok {
  94. t.Fatalf("should not be evicted")
  95. }
  96. }
  97. for i := 128; i < 192; i++ {
  98. l.Remove(i)
  99. _, ok := l.Get(i)
  100. if ok {
  101. t.Fatalf("should be deleted")
  102. }
  103. }
  104. l.Get(192) // expect 192 to be last key in l.Keys()
  105. for i, k := range l.Keys() {
  106. if (i < 63 && k != i+193) || (i == 63 && k != 192) {
  107. t.Fatalf("out of order key: %v", k)
  108. }
  109. }
  110. l.Purge()
  111. if l.Len() != 0 {
  112. t.Fatalf("bad len: %v", l.Len())
  113. }
  114. if _, ok := l.Get(200); ok {
  115. t.Fatalf("should contain nothing")
  116. }
  117. }
  118. // test that Add returns true/false if an eviction occurred
  119. func TestLRUAdd(t *testing.T) {
  120. evictCounter := 0
  121. onEvicted := func(k interface{}, v interface{}) {
  122. evictCounter++
  123. }
  124. l, err := NewWithEvict(1, onEvicted)
  125. if err != nil {
  126. t.Fatalf("err: %v", err)
  127. }
  128. if l.Add(1, 1) == true || evictCounter != 0 {
  129. t.Errorf("should not have an eviction")
  130. }
  131. if l.Add(2, 2) == false || evictCounter != 1 {
  132. t.Errorf("should have an eviction")
  133. }
  134. }
  135. // test that Contains doesn't update recent-ness
  136. func TestLRUContains(t *testing.T) {
  137. l, err := New(2)
  138. if err != nil {
  139. t.Fatalf("err: %v", err)
  140. }
  141. l.Add(1, 1)
  142. l.Add(2, 2)
  143. if !l.Contains(1) {
  144. t.Errorf("1 should be contained")
  145. }
  146. l.Add(3, 3)
  147. if l.Contains(1) {
  148. t.Errorf("Contains should not have updated recent-ness of 1")
  149. }
  150. }
  151. // test that Contains doesn't update recent-ness
  152. func TestLRUContainsOrAdd(t *testing.T) {
  153. l, err := New(2)
  154. if err != nil {
  155. t.Fatalf("err: %v", err)
  156. }
  157. l.Add(1, 1)
  158. l.Add(2, 2)
  159. contains, evict := l.ContainsOrAdd(1, 1)
  160. if !contains {
  161. t.Errorf("1 should be contained")
  162. }
  163. if evict {
  164. t.Errorf("nothing should be evicted here")
  165. }
  166. l.Add(3, 3)
  167. contains, evict = l.ContainsOrAdd(1, 1)
  168. if contains {
  169. t.Errorf("1 should not have been contained")
  170. }
  171. if !evict {
  172. t.Errorf("an eviction should have occurred")
  173. }
  174. if !l.Contains(1) {
  175. t.Errorf("now 1 should be contained")
  176. }
  177. }
  178. // test that Peek doesn't update recent-ness
  179. func TestLRUPeek(t *testing.T) {
  180. l, err := New(2)
  181. if err != nil {
  182. t.Fatalf("err: %v", err)
  183. }
  184. l.Add(1, 1)
  185. l.Add(2, 2)
  186. if v, ok := l.Peek(1); !ok || v != 1 {
  187. t.Errorf("1 should be set to 1: %v, %v", v, ok)
  188. }
  189. l.Add(3, 3)
  190. if l.Contains(1) {
  191. t.Errorf("should not have updated recent-ness of 1")
  192. }
  193. }