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.
 
 
 

378 lines
6.5 KiB

  1. package lru
  2. import (
  3. "math/rand"
  4. "testing"
  5. "time"
  6. )
  7. func init() {
  8. rand.Seed(time.Now().Unix())
  9. }
  10. func BenchmarkARC_Rand(b *testing.B) {
  11. l, err := NewARC(8192)
  12. if err != nil {
  13. b.Fatalf("err: %v", err)
  14. }
  15. trace := make([]int64, b.N*2)
  16. for i := 0; i < b.N*2; i++ {
  17. trace[i] = rand.Int63() % 32768
  18. }
  19. b.ResetTimer()
  20. var hit, miss int
  21. for i := 0; i < 2*b.N; i++ {
  22. if i%2 == 0 {
  23. l.Add(trace[i], trace[i])
  24. } else {
  25. _, ok := l.Get(trace[i])
  26. if ok {
  27. hit++
  28. } else {
  29. miss++
  30. }
  31. }
  32. }
  33. b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(miss))
  34. }
  35. func BenchmarkARC_Freq(b *testing.B) {
  36. l, err := NewARC(8192)
  37. if err != nil {
  38. b.Fatalf("err: %v", err)
  39. }
  40. trace := make([]int64, b.N*2)
  41. for i := 0; i < b.N*2; i++ {
  42. if i%2 == 0 {
  43. trace[i] = rand.Int63() % 16384
  44. } else {
  45. trace[i] = rand.Int63() % 32768
  46. }
  47. }
  48. b.ResetTimer()
  49. for i := 0; i < b.N; i++ {
  50. l.Add(trace[i], trace[i])
  51. }
  52. var hit, miss int
  53. for i := 0; i < b.N; i++ {
  54. _, ok := l.Get(trace[i])
  55. if ok {
  56. hit++
  57. } else {
  58. miss++
  59. }
  60. }
  61. b.Logf("hit: %d miss: %d ratio: %f", hit, miss, float64(hit)/float64(miss))
  62. }
  63. func TestARC_RandomOps(t *testing.T) {
  64. size := 128
  65. l, err := NewARC(128)
  66. if err != nil {
  67. t.Fatalf("err: %v", err)
  68. }
  69. n := 200000
  70. for i := 0; i < n; i++ {
  71. key := rand.Int63() % 512
  72. r := rand.Int63()
  73. switch r % 3 {
  74. case 0:
  75. l.Add(key, key)
  76. case 1:
  77. l.Get(key)
  78. case 2:
  79. l.Remove(key)
  80. }
  81. if l.t1.Len()+l.t2.Len() > size {
  82. t.Fatalf("bad: t1: %d t2: %d b1: %d b2: %d p: %d",
  83. l.t1.Len(), l.t2.Len(), l.b1.Len(), l.b2.Len(), l.p)
  84. }
  85. if l.b1.Len()+l.b2.Len() > size {
  86. t.Fatalf("bad: t1: %d t2: %d b1: %d b2: %d p: %d",
  87. l.t1.Len(), l.t2.Len(), l.b1.Len(), l.b2.Len(), l.p)
  88. }
  89. }
  90. }
  91. func TestARC_Get_RecentToFrequent(t *testing.T) {
  92. l, err := NewARC(128)
  93. if err != nil {
  94. t.Fatalf("err: %v", err)
  95. }
  96. // Touch all the entries, should be in t1
  97. for i := 0; i < 128; i++ {
  98. l.Add(i, i)
  99. }
  100. if n := l.t1.Len(); n != 128 {
  101. t.Fatalf("bad: %d", n)
  102. }
  103. if n := l.t2.Len(); n != 0 {
  104. t.Fatalf("bad: %d", n)
  105. }
  106. // Get should upgrade to t2
  107. for i := 0; i < 128; i++ {
  108. _, ok := l.Get(i)
  109. if !ok {
  110. t.Fatalf("missing: %d", i)
  111. }
  112. }
  113. if n := l.t1.Len(); n != 0 {
  114. t.Fatalf("bad: %d", n)
  115. }
  116. if n := l.t2.Len(); n != 128 {
  117. t.Fatalf("bad: %d", n)
  118. }
  119. // Get be from t2
  120. for i := 0; i < 128; i++ {
  121. _, ok := l.Get(i)
  122. if !ok {
  123. t.Fatalf("missing: %d", i)
  124. }
  125. }
  126. if n := l.t1.Len(); n != 0 {
  127. t.Fatalf("bad: %d", n)
  128. }
  129. if n := l.t2.Len(); n != 128 {
  130. t.Fatalf("bad: %d", n)
  131. }
  132. }
  133. func TestARC_Add_RecentToFrequent(t *testing.T) {
  134. l, err := NewARC(128)
  135. if err != nil {
  136. t.Fatalf("err: %v", err)
  137. }
  138. // Add initially to t1
  139. l.Add(1, 1)
  140. if n := l.t1.Len(); n != 1 {
  141. t.Fatalf("bad: %d", n)
  142. }
  143. if n := l.t2.Len(); n != 0 {
  144. t.Fatalf("bad: %d", n)
  145. }
  146. // Add should upgrade to t2
  147. l.Add(1, 1)
  148. if n := l.t1.Len(); n != 0 {
  149. t.Fatalf("bad: %d", n)
  150. }
  151. if n := l.t2.Len(); n != 1 {
  152. t.Fatalf("bad: %d", n)
  153. }
  154. // Add should remain in t2
  155. l.Add(1, 1)
  156. if n := l.t1.Len(); n != 0 {
  157. t.Fatalf("bad: %d", n)
  158. }
  159. if n := l.t2.Len(); n != 1 {
  160. t.Fatalf("bad: %d", n)
  161. }
  162. }
  163. func TestARC_Adaptive(t *testing.T) {
  164. l, err := NewARC(4)
  165. if err != nil {
  166. t.Fatalf("err: %v", err)
  167. }
  168. // Fill t1
  169. for i := 0; i < 4; i++ {
  170. l.Add(i, i)
  171. }
  172. if n := l.t1.Len(); n != 4 {
  173. t.Fatalf("bad: %d", n)
  174. }
  175. // Move to t2
  176. l.Get(0)
  177. l.Get(1)
  178. if n := l.t2.Len(); n != 2 {
  179. t.Fatalf("bad: %d", n)
  180. }
  181. // Evict from t1
  182. l.Add(4, 4)
  183. if n := l.b1.Len(); n != 1 {
  184. t.Fatalf("bad: %d", n)
  185. }
  186. // Current state
  187. // t1 : (MRU) [4, 3] (LRU)
  188. // t2 : (MRU) [1, 0] (LRU)
  189. // b1 : (MRU) [2] (LRU)
  190. // b2 : (MRU) [] (LRU)
  191. // Add 2, should cause hit on b1
  192. l.Add(2, 2)
  193. if n := l.b1.Len(); n != 1 {
  194. t.Fatalf("bad: %d", n)
  195. }
  196. if l.p != 1 {
  197. t.Fatalf("bad: %d", l.p)
  198. }
  199. if n := l.t2.Len(); n != 3 {
  200. t.Fatalf("bad: %d", n)
  201. }
  202. // Current state
  203. // t1 : (MRU) [4] (LRU)
  204. // t2 : (MRU) [2, 1, 0] (LRU)
  205. // b1 : (MRU) [3] (LRU)
  206. // b2 : (MRU) [] (LRU)
  207. // Add 4, should migrate to t2
  208. l.Add(4, 4)
  209. if n := l.t1.Len(); n != 0 {
  210. t.Fatalf("bad: %d", n)
  211. }
  212. if n := l.t2.Len(); n != 4 {
  213. t.Fatalf("bad: %d", n)
  214. }
  215. // Current state
  216. // t1 : (MRU) [] (LRU)
  217. // t2 : (MRU) [4, 2, 1, 0] (LRU)
  218. // b1 : (MRU) [3] (LRU)
  219. // b2 : (MRU) [] (LRU)
  220. // Add 4, should evict to b2
  221. l.Add(5, 5)
  222. if n := l.t1.Len(); n != 1 {
  223. t.Fatalf("bad: %d", n)
  224. }
  225. if n := l.t2.Len(); n != 3 {
  226. t.Fatalf("bad: %d", n)
  227. }
  228. if n := l.b2.Len(); n != 1 {
  229. t.Fatalf("bad: %d", n)
  230. }
  231. // Current state
  232. // t1 : (MRU) [5] (LRU)
  233. // t2 : (MRU) [4, 2, 1] (LRU)
  234. // b1 : (MRU) [3] (LRU)
  235. // b2 : (MRU) [0] (LRU)
  236. // Add 0, should decrease p
  237. l.Add(0, 0)
  238. if n := l.t1.Len(); n != 0 {
  239. t.Fatalf("bad: %d", n)
  240. }
  241. if n := l.t2.Len(); n != 4 {
  242. t.Fatalf("bad: %d", n)
  243. }
  244. if n := l.b1.Len(); n != 2 {
  245. t.Fatalf("bad: %d", n)
  246. }
  247. if n := l.b2.Len(); n != 0 {
  248. t.Fatalf("bad: %d", n)
  249. }
  250. if l.p != 0 {
  251. t.Fatalf("bad: %d", l.p)
  252. }
  253. // Current state
  254. // t1 : (MRU) [] (LRU)
  255. // t2 : (MRU) [0, 4, 2, 1] (LRU)
  256. // b1 : (MRU) [5, 3] (LRU)
  257. // b2 : (MRU) [0] (LRU)
  258. }
  259. func TestARC(t *testing.T) {
  260. l, err := NewARC(128)
  261. if err != nil {
  262. t.Fatalf("err: %v", err)
  263. }
  264. for i := 0; i < 256; i++ {
  265. l.Add(i, i)
  266. }
  267. if l.Len() != 128 {
  268. t.Fatalf("bad len: %v", l.Len())
  269. }
  270. for i, k := range l.Keys() {
  271. if v, ok := l.Get(k); !ok || v != k || v != i+128 {
  272. t.Fatalf("bad key: %v", k)
  273. }
  274. }
  275. for i := 0; i < 128; i++ {
  276. _, ok := l.Get(i)
  277. if ok {
  278. t.Fatalf("should be evicted")
  279. }
  280. }
  281. for i := 128; i < 256; i++ {
  282. _, ok := l.Get(i)
  283. if !ok {
  284. t.Fatalf("should not be evicted")
  285. }
  286. }
  287. for i := 128; i < 192; i++ {
  288. l.Remove(i)
  289. _, ok := l.Get(i)
  290. if ok {
  291. t.Fatalf("should be deleted")
  292. }
  293. }
  294. l.Purge()
  295. if l.Len() != 0 {
  296. t.Fatalf("bad len: %v", l.Len())
  297. }
  298. if _, ok := l.Get(200); ok {
  299. t.Fatalf("should contain nothing")
  300. }
  301. }
  302. // Test that Contains doesn't update recent-ness
  303. func TestARC_Contains(t *testing.T) {
  304. l, err := NewARC(2)
  305. if err != nil {
  306. t.Fatalf("err: %v", err)
  307. }
  308. l.Add(1, 1)
  309. l.Add(2, 2)
  310. if !l.Contains(1) {
  311. t.Errorf("1 should be contained")
  312. }
  313. l.Add(3, 3)
  314. if l.Contains(1) {
  315. t.Errorf("Contains should not have updated recent-ness of 1")
  316. }
  317. }
  318. // Test that Peek doesn't update recent-ness
  319. func TestARC_Peek(t *testing.T) {
  320. l, err := NewARC(2)
  321. if err != nil {
  322. t.Fatalf("err: %v", err)
  323. }
  324. l.Add(1, 1)
  325. l.Add(2, 2)
  326. if v, ok := l.Peek(1); !ok || v != 1 {
  327. t.Errorf("1 should be set to 1: %v, %v", v, ok)
  328. }
  329. l.Add(3, 3)
  330. if l.Contains(1) {
  331. t.Errorf("should not have updated recent-ness of 1")
  332. }
  333. }