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.
 
 
 

307 lines
5.3 KiB

  1. package lru
  2. import (
  3. "math/rand"
  4. "testing"
  5. )
  6. func Benchmark2Q_Rand(b *testing.B) {
  7. l, err := New2Q(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 Benchmark2Q_Freq(b *testing.B) {
  32. l, err := New2Q(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 Test2Q_RandomOps(t *testing.T) {
  60. size := 128
  61. l, err := New2Q(128)
  62. if err != nil {
  63. t.Fatalf("err: %v", err)
  64. }
  65. n := 200000
  66. for i := 0; i < n; i++ {
  67. key := rand.Int63() % 512
  68. r := rand.Int63()
  69. switch r % 3 {
  70. case 0:
  71. l.Add(key, key)
  72. case 1:
  73. l.Get(key)
  74. case 2:
  75. l.Remove(key)
  76. }
  77. if l.recent.Len()+l.frequent.Len() > size {
  78. t.Fatalf("bad: recent: %d freq: %d",
  79. l.recent.Len(), l.frequent.Len())
  80. }
  81. }
  82. }
  83. func Test2Q_Get_RecentToFrequent(t *testing.T) {
  84. l, err := New2Q(128)
  85. if err != nil {
  86. t.Fatalf("err: %v", err)
  87. }
  88. // Touch all the entries, should be in t1
  89. for i := 0; i < 128; i++ {
  90. l.Add(i, i)
  91. }
  92. if n := l.recent.Len(); n != 128 {
  93. t.Fatalf("bad: %d", n)
  94. }
  95. if n := l.frequent.Len(); n != 0 {
  96. t.Fatalf("bad: %d", n)
  97. }
  98. // Get should upgrade to t2
  99. for i := 0; i < 128; i++ {
  100. _, ok := l.Get(i)
  101. if !ok {
  102. t.Fatalf("missing: %d", i)
  103. }
  104. }
  105. if n := l.recent.Len(); n != 0 {
  106. t.Fatalf("bad: %d", n)
  107. }
  108. if n := l.frequent.Len(); n != 128 {
  109. t.Fatalf("bad: %d", n)
  110. }
  111. // Get be from t2
  112. for i := 0; i < 128; i++ {
  113. _, ok := l.Get(i)
  114. if !ok {
  115. t.Fatalf("missing: %d", i)
  116. }
  117. }
  118. if n := l.recent.Len(); n != 0 {
  119. t.Fatalf("bad: %d", n)
  120. }
  121. if n := l.frequent.Len(); n != 128 {
  122. t.Fatalf("bad: %d", n)
  123. }
  124. }
  125. func Test2Q_Add_RecentToFrequent(t *testing.T) {
  126. l, err := New2Q(128)
  127. if err != nil {
  128. t.Fatalf("err: %v", err)
  129. }
  130. // Add initially to recent
  131. l.Add(1, 1)
  132. if n := l.recent.Len(); n != 1 {
  133. t.Fatalf("bad: %d", n)
  134. }
  135. if n := l.frequent.Len(); n != 0 {
  136. t.Fatalf("bad: %d", n)
  137. }
  138. // Add should upgrade to frequent
  139. l.Add(1, 1)
  140. if n := l.recent.Len(); n != 0 {
  141. t.Fatalf("bad: %d", n)
  142. }
  143. if n := l.frequent.Len(); n != 1 {
  144. t.Fatalf("bad: %d", n)
  145. }
  146. // Add should remain in frequent
  147. l.Add(1, 1)
  148. if n := l.recent.Len(); n != 0 {
  149. t.Fatalf("bad: %d", n)
  150. }
  151. if n := l.frequent.Len(); n != 1 {
  152. t.Fatalf("bad: %d", n)
  153. }
  154. }
  155. func Test2Q_Add_RecentEvict(t *testing.T) {
  156. l, err := New2Q(4)
  157. if err != nil {
  158. t.Fatalf("err: %v", err)
  159. }
  160. // Add 1,2,3,4,5 -> Evict 1
  161. l.Add(1, 1)
  162. l.Add(2, 2)
  163. l.Add(3, 3)
  164. l.Add(4, 4)
  165. l.Add(5, 5)
  166. if n := l.recent.Len(); n != 4 {
  167. t.Fatalf("bad: %d", n)
  168. }
  169. if n := l.recentEvict.Len(); n != 1 {
  170. t.Fatalf("bad: %d", n)
  171. }
  172. if n := l.frequent.Len(); n != 0 {
  173. t.Fatalf("bad: %d", n)
  174. }
  175. // Pull in the recently evicted
  176. l.Add(1, 1)
  177. if n := l.recent.Len(); n != 3 {
  178. t.Fatalf("bad: %d", n)
  179. }
  180. if n := l.recentEvict.Len(); n != 1 {
  181. t.Fatalf("bad: %d", n)
  182. }
  183. if n := l.frequent.Len(); n != 1 {
  184. t.Fatalf("bad: %d", n)
  185. }
  186. // Add 6, should cause another recent evict
  187. l.Add(6, 6)
  188. if n := l.recent.Len(); n != 3 {
  189. t.Fatalf("bad: %d", n)
  190. }
  191. if n := l.recentEvict.Len(); n != 2 {
  192. t.Fatalf("bad: %d", n)
  193. }
  194. if n := l.frequent.Len(); n != 1 {
  195. t.Fatalf("bad: %d", n)
  196. }
  197. }
  198. func Test2Q(t *testing.T) {
  199. l, err := New2Q(128)
  200. if err != nil {
  201. t.Fatalf("err: %v", err)
  202. }
  203. for i := 0; i < 256; i++ {
  204. l.Add(i, i)
  205. }
  206. if l.Len() != 128 {
  207. t.Fatalf("bad len: %v", l.Len())
  208. }
  209. for i, k := range l.Keys() {
  210. if v, ok := l.Get(k); !ok || v != k || v != i+128 {
  211. t.Fatalf("bad key: %v", k)
  212. }
  213. }
  214. for i := 0; i < 128; i++ {
  215. _, ok := l.Get(i)
  216. if ok {
  217. t.Fatalf("should be evicted")
  218. }
  219. }
  220. for i := 128; i < 256; i++ {
  221. _, ok := l.Get(i)
  222. if !ok {
  223. t.Fatalf("should not be evicted")
  224. }
  225. }
  226. for i := 128; i < 192; i++ {
  227. l.Remove(i)
  228. _, ok := l.Get(i)
  229. if ok {
  230. t.Fatalf("should be deleted")
  231. }
  232. }
  233. l.Purge()
  234. if l.Len() != 0 {
  235. t.Fatalf("bad len: %v", l.Len())
  236. }
  237. if _, ok := l.Get(200); ok {
  238. t.Fatalf("should contain nothing")
  239. }
  240. }
  241. // Test that Contains doesn't update recent-ness
  242. func Test2Q_Contains(t *testing.T) {
  243. l, err := New2Q(2)
  244. if err != nil {
  245. t.Fatalf("err: %v", err)
  246. }
  247. l.Add(1, 1)
  248. l.Add(2, 2)
  249. if !l.Contains(1) {
  250. t.Errorf("1 should be contained")
  251. }
  252. l.Add(3, 3)
  253. if l.Contains(1) {
  254. t.Errorf("Contains should not have updated recent-ness of 1")
  255. }
  256. }
  257. // Test that Peek doesn't update recent-ness
  258. func Test2Q_Peek(t *testing.T) {
  259. l, err := New2Q(2)
  260. if err != nil {
  261. t.Fatalf("err: %v", err)
  262. }
  263. l.Add(1, 1)
  264. l.Add(2, 2)
  265. if v, ok := l.Peek(1); !ok || v != 1 {
  266. t.Errorf("1 should be set to 1: %v, %v", v, ok)
  267. }
  268. l.Add(3, 3)
  269. if l.Contains(1) {
  270. t.Errorf("should not have updated recent-ness of 1")
  271. }
  272. }