1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.io.hfile;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertTrue;
25
26 import java.nio.ByteBuffer;
27 import java.util.Random;
28
29 import org.apache.hadoop.hbase.testclassification.SmallTests;
30 import org.apache.hadoop.hbase.io.HeapSize;
31 import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread;
32 import org.apache.hadoop.hbase.util.ClassSize;
33 import org.junit.Test;
34 import org.junit.experimental.categories.Category;
35
36
37
38
39
40
41
42
43 @Category(SmallTests.class)
44 public class TestLruBlockCache {
45
46
47 @Test
48 public void testBackgroundEvictionThread() throws Exception {
49 long maxSize = 100000;
50 int numBlocks = 9;
51 long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);
52 assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks <= maxSize);
53
54 LruBlockCache cache = new LruBlockCache(maxSize,blockSize);
55 EvictionThread evictionThread = cache.getEvictionThread();
56 assertTrue(evictionThread != null);
57
58 CachedItem[] blocks = generateFixedBlocks(numBlocks + 1, blockSize, "block");
59
60
61 while (!evictionThread.isEnteringRun()) {
62 Thread.sleep(1);
63 }
64
65
66 for (CachedItem block : blocks) {
67 cache.cacheBlock(block.cacheKey, block);
68 }
69
70
71 int n = 0;
72 while(cache.getStats().getEvictionCount() == 0) {
73 Thread.sleep(200);
74 assertTrue("Eviction never happened.", n++ < 20);
75 }
76
77
78
79
80
81
82
83
84 n = 0;
85 for (long prevCnt = 0
86 curCnt = cache.getBlockCount();
87 prevCnt != curCnt; prevCnt = curCnt, curCnt = cache.getBlockCount()) {
88 Thread.sleep(200);
89 assertTrue("Cache never stabilized.", n++ < 20);
90 }
91
92 long evictionCount = cache.getStats().getEvictionCount();
93 assertTrue(evictionCount >= 1);
94 System.out.println("Background Evictions run: " + evictionCount);
95 }
96
97 @Test
98 public void testCacheSimple() throws Exception {
99
100 long maxSize = 1000000;
101 long blockSize = calculateBlockSizeDefault(maxSize, 101);
102
103 LruBlockCache cache = new LruBlockCache(maxSize, blockSize);
104
105 CachedItem [] blocks = generateRandomBlocks(100, blockSize);
106
107 long expectedCacheSize = cache.heapSize();
108
109
110 for (CachedItem block : blocks) {
111 assertTrue(cache.getBlock(block.cacheKey, true, false, true) == null);
112 }
113
114
115 for (CachedItem block : blocks) {
116 cache.cacheBlock(block.cacheKey, block);
117 expectedCacheSize += block.cacheBlockHeapSize();
118 }
119
120
121 assertEquals(expectedCacheSize, cache.heapSize());
122
123
124 for (CachedItem block : blocks) {
125 HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);
126 assertTrue(buf != null);
127 assertEquals(buf.heapSize(), block.heapSize());
128 }
129
130
131 long expectedBlockCount = cache.getBlockCount();
132 for (CachedItem block : blocks) {
133 cache.cacheBlock(block.cacheKey, block);
134 }
135 assertEquals(
136 "Cache should ignore cache requests for blocks already in cache",
137 expectedBlockCount, cache.getBlockCount());
138
139
140 assertEquals(expectedCacheSize, cache.heapSize());
141
142
143 for (CachedItem block : blocks) {
144 HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);
145 assertTrue(buf != null);
146 assertEquals(buf.heapSize(), block.heapSize());
147 }
148
149
150 assertEquals(0, cache.getStats().getEvictionCount());
151 Thread t = new LruBlockCache.StatisticsThread(cache);
152 t.start();
153 t.join();
154 }
155
156 @Test
157 public void testCacheEvictionSimple() throws Exception {
158
159 long maxSize = 100000;
160 long blockSize = calculateBlockSizeDefault(maxSize, 10);
161
162 LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);
163
164 CachedItem [] blocks = generateFixedBlocks(10, blockSize, "block");
165
166 long expectedCacheSize = cache.heapSize();
167
168
169 for (CachedItem block : blocks) {
170 cache.cacheBlock(block.cacheKey, block);
171 expectedCacheSize += block.cacheBlockHeapSize();
172 }
173
174
175 assertEquals(1, cache.getStats().getEvictionCount());
176
177
178 assertTrue(expectedCacheSize >
179 (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
180
181
182 assertTrue(cache.heapSize() < maxSize);
183
184
185 assertTrue(cache.heapSize() <
186 (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
187
188
189 assertTrue(cache.getBlock(blocks[0].cacheKey, true, false, true) == null);
190 for(int i=1;i<blocks.length;i++) {
191 assertEquals(cache.getBlock(blocks[i].cacheKey, true, false, true),
192 blocks[i]);
193 }
194 }
195
196 @Test
197 public void testCacheEvictionTwoPriorities() throws Exception {
198
199 long maxSize = 100000;
200 long blockSize = calculateBlockSizeDefault(maxSize, 10);
201
202 LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);
203
204 CachedItem [] singleBlocks = generateFixedBlocks(5, 10000, "single");
205 CachedItem [] multiBlocks = generateFixedBlocks(5, 10000, "multi");
206
207 long expectedCacheSize = cache.heapSize();
208
209
210 for (CachedItem block : multiBlocks) {
211 cache.cacheBlock(block.cacheKey, block);
212 expectedCacheSize += block.cacheBlockHeapSize();
213 assertEquals(cache.getBlock(block.cacheKey, true, false, true), block);
214 }
215
216
217 for (CachedItem block : singleBlocks) {
218 cache.cacheBlock(block.cacheKey, block);
219 expectedCacheSize += block.heapSize();
220 }
221
222
223 assertEquals(cache.getStats().getEvictionCount(), 1);
224
225
226 assertEquals(cache.getStats().getEvictedCount(), 2);
227
228
229 assertTrue(expectedCacheSize >
230 (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
231
232
233 assertTrue(cache.heapSize() <= maxSize);
234
235
236 assertTrue(cache.heapSize() <=
237 (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
238
239
240
241
242
243 assertTrue(cache.getBlock(singleBlocks[0].cacheKey, true, false, true) == null);
244 assertTrue(cache.getBlock(multiBlocks[0].cacheKey, true, false, true) == null);
245
246
247 for(int i=1;i<4;i++) {
248 assertEquals(cache.getBlock(singleBlocks[i].cacheKey, true, false, true),
249 singleBlocks[i]);
250 assertEquals(cache.getBlock(multiBlocks[i].cacheKey, true, false, true),
251 multiBlocks[i]);
252 }
253 }
254
255 @Test
256 public void testCacheEvictionThreePriorities() throws Exception {
257
258 long maxSize = 100000;
259 long blockSize = calculateBlockSize(maxSize, 10);
260
261 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
262 (int)Math.ceil(1.2*maxSize/blockSize),
263 LruBlockCache.DEFAULT_LOAD_FACTOR,
264 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
265 0.98f,
266 0.99f,
267 0.33f,
268 0.33f,
269 0.34f,
270 false,
271 16 * 1024 * 1024);
272
273 CachedItem [] singleBlocks = generateFixedBlocks(5, blockSize, "single");
274 CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");
275 CachedItem [] memoryBlocks = generateFixedBlocks(5, blockSize, "memory");
276
277 long expectedCacheSize = cache.heapSize();
278
279
280 for(int i=0;i<3;i++) {
281
282
283 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
284 expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();
285
286
287 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
288 expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();
289 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
290
291
292 cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true, false);
293 expectedCacheSize += memoryBlocks[i].cacheBlockHeapSize();
294
295 }
296
297
298 assertEquals(0, cache.getStats().getEvictionCount());
299
300
301 assertEquals(expectedCacheSize, cache.heapSize());
302
303
304 cache.cacheBlock(singleBlocks[3].cacheKey, singleBlocks[3]);
305
306
307 assertEquals(1, cache.getStats().getEvictionCount());
308 assertEquals(1, cache.getStats().getEvictedCount());
309
310
311 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
312
313
314 cache.getBlock(singleBlocks[1].cacheKey, true, false, true);
315
316
317 cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);
318
319
320 assertEquals(2, cache.getStats().getEvictionCount());
321 assertEquals(2, cache.getStats().getEvictedCount());
322
323
324 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
325
326
327 cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true, false);
328
329
330 assertEquals(3, cache.getStats().getEvictionCount());
331 assertEquals(3, cache.getStats().getEvictedCount());
332
333
334 assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));
335
336
337 CachedItem [] bigBlocks = generateFixedBlocks(3, blockSize*3, "big");
338 cache.cacheBlock(bigBlocks[0].cacheKey, bigBlocks[0]);
339
340
341 assertEquals(4, cache.getStats().getEvictionCount());
342 assertEquals(6, cache.getStats().getEvictedCount());
343
344
345 assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));
346 assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));
347 assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));
348
349
350 cache.getBlock(bigBlocks[0].cacheKey, true, false, true);
351
352
353 cache.cacheBlock(bigBlocks[1].cacheKey, bigBlocks[1]);
354
355
356 assertEquals(5, cache.getStats().getEvictionCount());
357 assertEquals(9, cache.getStats().getEvictedCount());
358
359
360 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
361 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
362 assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));
363
364
365 cache.cacheBlock(bigBlocks[2].cacheKey, bigBlocks[2], true, false);
366
367
368 assertEquals(6, cache.getStats().getEvictionCount());
369 assertEquals(12, cache.getStats().getEvictedCount());
370
371
372 assertEquals(null, cache.getBlock(memoryBlocks[1].cacheKey, true, false, true));
373 assertEquals(null, cache.getBlock(memoryBlocks[2].cacheKey, true, false, true));
374 assertEquals(null, cache.getBlock(memoryBlocks[3].cacheKey, true, false, true));
375 }
376
377 @Test
378 public void testCacheEvictionInMemoryForceMode() throws Exception {
379 long maxSize = 100000;
380 long blockSize = calculateBlockSize(maxSize, 10);
381
382 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
383 (int)Math.ceil(1.2*maxSize/blockSize),
384 LruBlockCache.DEFAULT_LOAD_FACTOR,
385 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
386 0.98f,
387 0.99f,
388 0.2f,
389 0.3f,
390 0.5f,
391 true,
392 16 * 1024 * 1024);
393
394 CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");
395 CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");
396 CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");
397
398 long expectedCacheSize = cache.heapSize();
399
400
401 for(int i = 0; i < 4; i++) {
402
403 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
404 expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();
405
406 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
407 expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();
408 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
409 }
410
411 cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);
412 expectedCacheSize += singleBlocks[4].cacheBlockHeapSize();
413
414 assertEquals(0, cache.getStats().getEvictionCount());
415
416 assertEquals(expectedCacheSize, cache.heapSize());
417
418
419 cache.cacheBlock(memoryBlocks[0].cacheKey, memoryBlocks[0], true, false);
420
421 assertEquals(1, cache.getStats().getEvictionCount());
422 assertEquals(1, cache.getStats().getEvictedCount());
423
424 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
425
426
427 cache.cacheBlock(memoryBlocks[1].cacheKey, memoryBlocks[1], true, false);
428
429 assertEquals(2, cache.getStats().getEvictionCount());
430 assertEquals(2, cache.getStats().getEvictedCount());
431
432 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
433
434
435 cache.cacheBlock(memoryBlocks[2].cacheKey, memoryBlocks[2], true, false);
436 cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true, false);
437 cache.cacheBlock(memoryBlocks[4].cacheKey, memoryBlocks[4], true, false);
438 cache.cacheBlock(memoryBlocks[5].cacheKey, memoryBlocks[5], true, false);
439
440 assertEquals(6, cache.getStats().getEvictionCount());
441 assertEquals(6, cache.getStats().getEvictedCount());
442
443 assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));
444 assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));
445 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
446 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
447
448
449
450 cache.cacheBlock(memoryBlocks[6].cacheKey, memoryBlocks[6], true, false);
451 cache.cacheBlock(memoryBlocks[7].cacheKey, memoryBlocks[7], true, false);
452 cache.cacheBlock(memoryBlocks[8].cacheKey, memoryBlocks[8], true, false);
453
454 assertEquals(9, cache.getStats().getEvictionCount());
455 assertEquals(9, cache.getStats().getEvictedCount());
456
457 assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));
458 assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));
459 assertEquals(null, cache.getBlock(multiBlocks[3].cacheKey, true, false, true));
460
461
462
463 cache.cacheBlock(memoryBlocks[9].cacheKey, memoryBlocks[9], true, false);
464
465 assertEquals(10, cache.getStats().getEvictionCount());
466 assertEquals(10, cache.getStats().getEvictedCount());
467
468 assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));
469
470
471
472
473 cache.cacheBlock(singleBlocks[9].cacheKey, singleBlocks[9]);
474
475 assertEquals(11, cache.getStats().getEvictionCount());
476 assertEquals(11, cache.getStats().getEvictedCount());
477
478 assertEquals(null, cache.getBlock(singleBlocks[9].cacheKey, true, false, true));
479 }
480
481
482 @Test
483 public void testScanResistance() throws Exception {
484
485 long maxSize = 100000;
486 long blockSize = calculateBlockSize(maxSize, 10);
487
488 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
489 (int)Math.ceil(1.2*maxSize/blockSize),
490 LruBlockCache.DEFAULT_LOAD_FACTOR,
491 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
492 0.66f,
493 0.99f,
494 0.33f,
495 0.33f,
496 0.34f,
497 false,
498 16 * 1024 * 1024);
499
500 CachedItem [] singleBlocks = generateFixedBlocks(20, blockSize, "single");
501 CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");
502
503
504 for (CachedItem block : multiBlocks) {
505 cache.cacheBlock(block.cacheKey, block);
506 cache.getBlock(block.cacheKey, true, false, true);
507 }
508
509
510 for(int i=0;i<5;i++) {
511 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
512 }
513
514
515 assertEquals(1, cache.getStats().getEvictionCount());
516
517
518 assertEquals(4, cache.getStats().getEvictedCount());
519
520
521 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
522 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
523 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
524 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
525
526
527
528
529
530
531
532
533 for(int i=5;i<18;i++) {
534 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
535 }
536
537
538 assertEquals(4, cache.getStats().getEvictionCount());
539 assertEquals(16, cache.getStats().getEvictedCount());
540
541
542 assertEquals(7, cache.getBlockCount());
543
544 }
545
546 @Test
547 public void testMaxBlockSize() throws Exception {
548 long maxSize = 100000;
549 long blockSize = calculateBlockSize(maxSize, 10);
550
551 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
552 (int)Math.ceil(1.2*maxSize/blockSize),
553 LruBlockCache.DEFAULT_LOAD_FACTOR,
554 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
555 0.66f,
556 0.99f,
557 0.33f,
558 0.33f,
559 0.34f,
560 false,
561 1024);
562 CachedItem [] tooLong = generateFixedBlocks(10, 1024+5, "long");
563 CachedItem [] small = generateFixedBlocks(15, 600, "small");
564
565
566 for (CachedItem i:tooLong) {
567 cache.cacheBlock(i.cacheKey, i);
568 }
569 for (CachedItem i:small) {
570 cache.cacheBlock(i.cacheKey, i);
571 }
572 assertEquals(15,cache.getBlockCount());
573 for (CachedItem i:small) {
574 assertNotNull(cache.getBlock(i.cacheKey, true, false, false));
575 }
576 for (CachedItem i:tooLong) {
577 assertNull(cache.getBlock(i.cacheKey, true, false, false));
578 }
579
580 assertEquals(10, cache.getStats().getFailedInserts());
581 }
582
583
584 @Test
585 public void testResizeBlockCache() throws Exception {
586
587 long maxSize = 300000;
588 long blockSize = calculateBlockSize(maxSize, 31);
589
590 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
591 (int)Math.ceil(1.2*maxSize/blockSize),
592 LruBlockCache.DEFAULT_LOAD_FACTOR,
593 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
594 0.98f,
595 0.99f,
596 0.33f,
597 0.33f,
598 0.34f,
599 false,
600 16 * 1024 * 1024);
601
602 CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");
603 CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");
604 CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");
605
606
607 for(int i=0;i<10;i++) {
608
609
610 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
611
612
613 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
614 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
615
616
617 cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true, false);
618 }
619
620
621 assertEquals(0, cache.getStats().getEvictionCount());
622
623
624 cache.setMaxSize((long)(maxSize * 0.5f));
625
626
627 assertEquals(1, cache.getStats().getEvictionCount());
628
629
630 assertEquals(15, cache.getStats().getEvictedCount());
631
632
633 for(int i=0;i<5;i++) {
634 assertEquals(null, cache.getBlock(singleBlocks[i].cacheKey, true, false, true));
635 assertEquals(null, cache.getBlock(multiBlocks[i].cacheKey, true, false, true));
636 assertEquals(null, cache.getBlock(memoryBlocks[i].cacheKey, true, false, true));
637 }
638
639
640 for(int i=5;i<10;i++) {
641 assertEquals(singleBlocks[i], cache.getBlock(singleBlocks[i].cacheKey, true, false, true));
642 assertEquals(multiBlocks[i], cache.getBlock(multiBlocks[i].cacheKey, true, false, true));
643 assertEquals(memoryBlocks[i], cache.getBlock(memoryBlocks[i].cacheKey, true, false, true));
644 }
645 }
646
647
648 @Test
649 public void testPastNPeriodsMetrics() throws Exception {
650 double delta = 0.01;
651
652
653 CacheStats stats = new CacheStats("test", 3);
654
655
656 stats.rollMetricsPeriod();
657 assertEquals(0.0, stats.getHitRatioPastNPeriods(), delta);
658 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
659
660
661
662 stats.hit(false);
663 stats.hit(true);
664 stats.miss(false, false);
665 stats.miss(false, false);
666 stats.rollMetricsPeriod();
667 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
668 assertEquals(1.0, stats.getHitCachingRatioPastNPeriods(), delta);
669
670
671
672 stats.miss(true, false);
673 stats.miss(false, false);
674 stats.miss(false, false);
675 stats.miss(false, false);
676 stats.rollMetricsPeriod();
677 assertEquals(0.25, stats.getHitRatioPastNPeriods(), delta);
678 assertEquals(0.5, stats.getHitCachingRatioPastNPeriods(), delta);
679
680
681
682 stats.hit(false);
683 stats.hit(true);
684 stats.hit(false);
685 stats.hit(true);
686 stats.rollMetricsPeriod();
687 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
688 assertEquals(0.75, stats.getHitCachingRatioPastNPeriods(), delta);
689
690
691
692 stats.miss(true, false);
693 stats.miss(true, false);
694 stats.rollMetricsPeriod();
695 assertEquals(0.4, stats.getHitRatioPastNPeriods(), delta);
696 assertEquals(0.4, stats.getHitCachingRatioPastNPeriods(), delta);
697
698
699
700 stats.miss(true, false);
701 stats.miss(true, false);
702 stats.hit(false);
703 stats.hit(false);
704 stats.rollMetricsPeriod();
705 assertEquals(0.6, stats.getHitRatioPastNPeriods(), delta);
706 assertEquals((double)1/3, stats.getHitCachingRatioPastNPeriods(), delta);
707
708
709
710 stats.rollMetricsPeriod();
711 assertEquals((double)1/3, stats.getHitRatioPastNPeriods(), delta);
712 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
713
714
715
716 stats.rollMetricsPeriod();
717 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
718 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
719
720
721
722 stats.rollMetricsPeriod();
723 assertEquals(0.0, stats.getHitRatioPastNPeriods(), delta);
724 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
725
726
727
728 stats.miss(true, false);
729 stats.miss(false, false);
730 stats.hit(true);
731 stats.hit(false);
732 stats.rollMetricsPeriod();
733 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
734 assertEquals(0.5, stats.getHitCachingRatioPastNPeriods(), delta);
735 }
736
737 private CachedItem [] generateFixedBlocks(int numBlocks, int size, String pfx) {
738 CachedItem [] blocks = new CachedItem[numBlocks];
739 for(int i=0;i<numBlocks;i++) {
740 blocks[i] = new CachedItem(pfx + i, size);
741 }
742 return blocks;
743 }
744
745 private CachedItem [] generateFixedBlocks(int numBlocks, long size, String pfx) {
746 return generateFixedBlocks(numBlocks, (int)size, pfx);
747 }
748
749 private CachedItem [] generateRandomBlocks(int numBlocks, long maxSize) {
750 CachedItem [] blocks = new CachedItem[numBlocks];
751 Random r = new Random();
752 for(int i=0;i<numBlocks;i++) {
753 blocks[i] = new CachedItem("block" + i, r.nextInt((int)maxSize)+1);
754 }
755 return blocks;
756 }
757
758 private long calculateBlockSize(long maxSize, int numBlocks) {
759 long roughBlockSize = maxSize / numBlocks;
760 int numEntries = (int)Math.ceil((1.2)*maxSize/roughBlockSize);
761 long totalOverhead = LruBlockCache.CACHE_FIXED_OVERHEAD +
762 ClassSize.CONCURRENT_HASHMAP +
763 (numEntries * ClassSize.CONCURRENT_HASHMAP_ENTRY) +
764 (LruBlockCache.DEFAULT_CONCURRENCY_LEVEL * ClassSize.CONCURRENT_HASHMAP_SEGMENT);
765 long negateBlockSize = (long)(totalOverhead/numEntries);
766 negateBlockSize += LruCachedBlock.PER_BLOCK_OVERHEAD;
767 return ClassSize.align((long)Math.floor((roughBlockSize - negateBlockSize)*0.99f));
768 }
769
770 private long calculateBlockSizeDefault(long maxSize, int numBlocks) {
771 long roughBlockSize = maxSize / numBlocks;
772 int numEntries = (int)Math.ceil((1.2)*maxSize/roughBlockSize);
773 long totalOverhead = LruBlockCache.CACHE_FIXED_OVERHEAD +
774 ClassSize.CONCURRENT_HASHMAP +
775 (numEntries * ClassSize.CONCURRENT_HASHMAP_ENTRY) +
776 (LruBlockCache.DEFAULT_CONCURRENCY_LEVEL * ClassSize.CONCURRENT_HASHMAP_SEGMENT);
777 long negateBlockSize = totalOverhead / numEntries;
778 negateBlockSize += LruCachedBlock.PER_BLOCK_OVERHEAD;
779 return ClassSize.align((long)Math.floor((roughBlockSize - negateBlockSize)*
780 LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
781 }
782
783 private static class CachedItem implements Cacheable {
784 BlockCacheKey cacheKey;
785 int size;
786
787 CachedItem(String blockName, int size) {
788 this.cacheKey = new BlockCacheKey(blockName, 0);
789 this.size = size;
790 }
791
792
793 @Override
794 public long heapSize() {
795 return ClassSize.align(size);
796 }
797
798
799 public long cacheBlockHeapSize() {
800 return LruCachedBlock.PER_BLOCK_OVERHEAD
801 + ClassSize.align(cacheKey.heapSize())
802 + ClassSize.align(size);
803 }
804
805 @Override
806 public int getSerializedLength() {
807 return 0;
808 }
809
810 @Override
811 public CacheableDeserializer<Cacheable> getDeserializer() {
812 return null;
813 }
814
815 @Override
816 public void serialize(ByteBuffer destination) {
817 }
818
819 @Override
820 public BlockType getBlockType() {
821 return BlockType.DATA;
822 }
823
824 }
825
826 }
827