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 1.2f,
271 false,
272 16 * 1024 * 1024);
273
274 CachedItem [] singleBlocks = generateFixedBlocks(5, blockSize, "single");
275 CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");
276 CachedItem [] memoryBlocks = generateFixedBlocks(5, blockSize, "memory");
277
278 long expectedCacheSize = cache.heapSize();
279
280
281 for(int i=0;i<3;i++) {
282
283
284 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
285 expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();
286
287
288 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
289 expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();
290 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
291
292
293 cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true, false);
294 expectedCacheSize += memoryBlocks[i].cacheBlockHeapSize();
295
296 }
297
298
299 assertEquals(0, cache.getStats().getEvictionCount());
300
301
302 assertEquals(expectedCacheSize, cache.heapSize());
303
304
305 cache.cacheBlock(singleBlocks[3].cacheKey, singleBlocks[3]);
306
307
308 assertEquals(1, cache.getStats().getEvictionCount());
309 assertEquals(1, cache.getStats().getEvictedCount());
310
311
312 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
313
314
315 cache.getBlock(singleBlocks[1].cacheKey, true, false, true);
316
317
318 cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);
319
320
321 assertEquals(2, cache.getStats().getEvictionCount());
322 assertEquals(2, cache.getStats().getEvictedCount());
323
324
325 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
326
327
328 cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true, false);
329
330
331 assertEquals(3, cache.getStats().getEvictionCount());
332 assertEquals(3, cache.getStats().getEvictedCount());
333
334
335 assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));
336
337
338 CachedItem [] bigBlocks = generateFixedBlocks(3, blockSize*3, "big");
339 cache.cacheBlock(bigBlocks[0].cacheKey, bigBlocks[0]);
340
341
342 assertEquals(4, cache.getStats().getEvictionCount());
343 assertEquals(6, cache.getStats().getEvictedCount());
344
345
346 assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));
347 assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));
348 assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));
349
350
351 cache.getBlock(bigBlocks[0].cacheKey, true, false, true);
352
353
354 cache.cacheBlock(bigBlocks[1].cacheKey, bigBlocks[1]);
355
356
357 assertEquals(5, cache.getStats().getEvictionCount());
358 assertEquals(9, cache.getStats().getEvictedCount());
359
360
361 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
362 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
363 assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));
364
365
366 cache.cacheBlock(bigBlocks[2].cacheKey, bigBlocks[2], true, false);
367
368
369 assertEquals(6, cache.getStats().getEvictionCount());
370 assertEquals(12, cache.getStats().getEvictedCount());
371
372
373 assertEquals(null, cache.getBlock(memoryBlocks[1].cacheKey, true, false, true));
374 assertEquals(null, cache.getBlock(memoryBlocks[2].cacheKey, true, false, true));
375 assertEquals(null, cache.getBlock(memoryBlocks[3].cacheKey, true, false, true));
376 }
377
378 @Test
379 public void testCacheEvictionInMemoryForceMode() throws Exception {
380 long maxSize = 100000;
381 long blockSize = calculateBlockSize(maxSize, 10);
382
383 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
384 (int)Math.ceil(1.2*maxSize/blockSize),
385 LruBlockCache.DEFAULT_LOAD_FACTOR,
386 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
387 0.98f,
388 0.99f,
389 0.2f,
390 0.3f,
391 0.5f,
392 1.2f,
393 true,
394 16 * 1024 * 1024);
395
396 CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");
397 CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");
398 CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");
399
400 long expectedCacheSize = cache.heapSize();
401
402
403 for(int i = 0; i < 4; i++) {
404
405 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
406 expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();
407
408 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
409 expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();
410 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
411 }
412
413 cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);
414 expectedCacheSize += singleBlocks[4].cacheBlockHeapSize();
415
416 assertEquals(0, cache.getStats().getEvictionCount());
417
418 assertEquals(expectedCacheSize, cache.heapSize());
419
420
421 cache.cacheBlock(memoryBlocks[0].cacheKey, memoryBlocks[0], true, false);
422
423 assertEquals(1, cache.getStats().getEvictionCount());
424 assertEquals(1, cache.getStats().getEvictedCount());
425
426 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
427
428
429 cache.cacheBlock(memoryBlocks[1].cacheKey, memoryBlocks[1], true, false);
430
431 assertEquals(2, cache.getStats().getEvictionCount());
432 assertEquals(2, cache.getStats().getEvictedCount());
433
434 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
435
436
437 cache.cacheBlock(memoryBlocks[2].cacheKey, memoryBlocks[2], true, false);
438 cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true, false);
439 cache.cacheBlock(memoryBlocks[4].cacheKey, memoryBlocks[4], true, false);
440 cache.cacheBlock(memoryBlocks[5].cacheKey, memoryBlocks[5], true, false);
441
442 assertEquals(6, cache.getStats().getEvictionCount());
443 assertEquals(6, cache.getStats().getEvictedCount());
444
445 assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));
446 assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));
447 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
448 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
449
450
451
452 cache.cacheBlock(memoryBlocks[6].cacheKey, memoryBlocks[6], true, false);
453 cache.cacheBlock(memoryBlocks[7].cacheKey, memoryBlocks[7], true, false);
454 cache.cacheBlock(memoryBlocks[8].cacheKey, memoryBlocks[8], true, false);
455
456 assertEquals(9, cache.getStats().getEvictionCount());
457 assertEquals(9, cache.getStats().getEvictedCount());
458
459 assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));
460 assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));
461 assertEquals(null, cache.getBlock(multiBlocks[3].cacheKey, true, false, true));
462
463
464
465 cache.cacheBlock(memoryBlocks[9].cacheKey, memoryBlocks[9], true, false);
466
467 assertEquals(10, cache.getStats().getEvictionCount());
468 assertEquals(10, cache.getStats().getEvictedCount());
469
470 assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));
471
472
473
474
475 cache.cacheBlock(singleBlocks[9].cacheKey, singleBlocks[9]);
476
477 assertEquals(11, cache.getStats().getEvictionCount());
478 assertEquals(11, cache.getStats().getEvictedCount());
479
480 assertEquals(null, cache.getBlock(singleBlocks[9].cacheKey, true, false, true));
481 }
482
483
484 @Test
485 public void testScanResistance() throws Exception {
486
487 long maxSize = 100000;
488 long blockSize = calculateBlockSize(maxSize, 10);
489
490 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
491 (int)Math.ceil(1.2*maxSize/blockSize),
492 LruBlockCache.DEFAULT_LOAD_FACTOR,
493 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
494 0.66f,
495 0.99f,
496 0.33f,
497 0.33f,
498 0.34f,
499 1.2f,
500 false,
501 16 * 1024 * 1024);
502
503 CachedItem [] singleBlocks = generateFixedBlocks(20, blockSize, "single");
504 CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");
505
506
507 for (CachedItem block : multiBlocks) {
508 cache.cacheBlock(block.cacheKey, block);
509 cache.getBlock(block.cacheKey, true, false, true);
510 }
511
512
513 for(int i=0;i<5;i++) {
514 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
515 }
516
517
518 assertEquals(1, cache.getStats().getEvictionCount());
519
520
521 assertEquals(4, cache.getStats().getEvictedCount());
522
523
524 assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));
525 assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));
526 assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));
527 assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));
528
529
530
531
532
533
534
535
536 for(int i=5;i<18;i++) {
537 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
538 }
539
540
541 assertEquals(4, cache.getStats().getEvictionCount());
542 assertEquals(16, cache.getStats().getEvictedCount());
543
544
545 assertEquals(7, cache.getBlockCount());
546
547 }
548
549 @Test
550 public void testMaxBlockSize() throws Exception {
551 long maxSize = 100000;
552 long blockSize = calculateBlockSize(maxSize, 10);
553
554 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
555 (int)Math.ceil(1.2*maxSize/blockSize),
556 LruBlockCache.DEFAULT_LOAD_FACTOR,
557 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
558 0.66f,
559 0.99f,
560 0.33f,
561 0.33f,
562 0.34f,
563 1.2f,
564 false,
565 1024);
566 CachedItem [] tooLong = generateFixedBlocks(10, 1024+5, "long");
567 CachedItem [] small = generateFixedBlocks(15, 600, "small");
568
569
570 for (CachedItem i:tooLong) {
571 cache.cacheBlock(i.cacheKey, i);
572 }
573 for (CachedItem i:small) {
574 cache.cacheBlock(i.cacheKey, i);
575 }
576 assertEquals(15,cache.getBlockCount());
577 for (CachedItem i:small) {
578 assertNotNull(cache.getBlock(i.cacheKey, true, false, false));
579 }
580 for (CachedItem i:tooLong) {
581 assertNull(cache.getBlock(i.cacheKey, true, false, false));
582 }
583
584 assertEquals(10, cache.getStats().getFailedInserts());
585 }
586
587
588 @Test
589 public void testResizeBlockCache() throws Exception {
590
591 long maxSize = 300000;
592 long blockSize = calculateBlockSize(maxSize, 31);
593
594 LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,
595 (int)Math.ceil(1.2*maxSize/blockSize),
596 LruBlockCache.DEFAULT_LOAD_FACTOR,
597 LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,
598 0.98f,
599 0.99f,
600 0.33f,
601 0.33f,
602 0.34f,
603 1.2f,
604 false,
605 16 * 1024 * 1024);
606
607 CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");
608 CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");
609 CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");
610
611
612 for(int i=0;i<10;i++) {
613
614
615 cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);
616
617
618 cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);
619 cache.getBlock(multiBlocks[i].cacheKey, true, false, true);
620
621
622 cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true, false);
623 }
624
625
626 assertEquals(0, cache.getStats().getEvictionCount());
627
628
629 cache.setMaxSize((long)(maxSize * 0.5f));
630
631
632 assertEquals(1, cache.getStats().getEvictionCount());
633
634
635 assertEquals(15, cache.getStats().getEvictedCount());
636
637
638 for(int i=0;i<5;i++) {
639 assertEquals(null, cache.getBlock(singleBlocks[i].cacheKey, true, false, true));
640 assertEquals(null, cache.getBlock(multiBlocks[i].cacheKey, true, false, true));
641 assertEquals(null, cache.getBlock(memoryBlocks[i].cacheKey, true, false, true));
642 }
643
644
645 for(int i=5;i<10;i++) {
646 assertEquals(singleBlocks[i], cache.getBlock(singleBlocks[i].cacheKey, true, false, true));
647 assertEquals(multiBlocks[i], cache.getBlock(multiBlocks[i].cacheKey, true, false, true));
648 assertEquals(memoryBlocks[i], cache.getBlock(memoryBlocks[i].cacheKey, true, false, true));
649 }
650 }
651
652
653 @Test
654 public void testPastNPeriodsMetrics() throws Exception {
655 double delta = 0.01;
656
657
658 CacheStats stats = new CacheStats("test", 3);
659
660
661 stats.rollMetricsPeriod();
662 assertEquals(0.0, stats.getHitRatioPastNPeriods(), delta);
663 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
664
665
666
667 stats.hit(false, true, BlockType.DATA);
668 stats.hit(true, true, BlockType.DATA);
669 stats.miss(false, false, BlockType.DATA);
670 stats.miss(false, false, BlockType.DATA);
671 stats.rollMetricsPeriod();
672 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
673 assertEquals(1.0, stats.getHitCachingRatioPastNPeriods(), delta);
674
675
676
677 stats.miss(true, false, BlockType.DATA);
678 stats.miss(false, false, BlockType.DATA);
679 stats.miss(false, false, BlockType.DATA);
680 stats.miss(false, false, BlockType.DATA);
681 stats.rollMetricsPeriod();
682 assertEquals(0.25, stats.getHitRatioPastNPeriods(), delta);
683 assertEquals(0.5, stats.getHitCachingRatioPastNPeriods(), delta);
684
685
686
687 stats.hit(false, true, BlockType.DATA);
688 stats.hit(true, true, BlockType.DATA);
689 stats.hit(false, true, BlockType.DATA);
690 stats.hit(true, true, BlockType.DATA);
691 stats.rollMetricsPeriod();
692 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
693 assertEquals(0.75, stats.getHitCachingRatioPastNPeriods(), delta);
694
695
696
697 stats.miss(true, false, BlockType.DATA);
698 stats.miss(true, false, BlockType.DATA);
699 stats.rollMetricsPeriod();
700 assertEquals(0.4, stats.getHitRatioPastNPeriods(), delta);
701 assertEquals(0.4, stats.getHitCachingRatioPastNPeriods(), delta);
702
703
704
705 stats.miss(true, false, BlockType.DATA);
706 stats.miss(true, false, BlockType.DATA);
707 stats.hit(false, true, BlockType.DATA);
708 stats.hit(false, true, BlockType.DATA);
709 stats.rollMetricsPeriod();
710 assertEquals(0.6, stats.getHitRatioPastNPeriods(), delta);
711 assertEquals((double)1/3, stats.getHitCachingRatioPastNPeriods(), delta);
712
713
714
715 stats.rollMetricsPeriod();
716 assertEquals((double)1/3, stats.getHitRatioPastNPeriods(), delta);
717 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
718
719
720
721 stats.rollMetricsPeriod();
722 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
723 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
724
725
726
727 stats.rollMetricsPeriod();
728 assertEquals(0.0, stats.getHitRatioPastNPeriods(), delta);
729 assertEquals(0.0, stats.getHitCachingRatioPastNPeriods(), delta);
730
731
732
733 stats.miss(true, false, BlockType.DATA);
734 stats.miss(false, false, BlockType.DATA);
735 stats.hit(true, true, BlockType.DATA);
736 stats.hit(false, true, BlockType.DATA);
737 stats.rollMetricsPeriod();
738 assertEquals(0.5, stats.getHitRatioPastNPeriods(), delta);
739 assertEquals(0.5, stats.getHitCachingRatioPastNPeriods(), delta);
740 }
741
742 private CachedItem [] generateFixedBlocks(int numBlocks, int size, String pfx) {
743 CachedItem [] blocks = new CachedItem[numBlocks];
744 for(int i=0;i<numBlocks;i++) {
745 blocks[i] = new CachedItem(pfx + i, size);
746 }
747 return blocks;
748 }
749
750 private CachedItem [] generateFixedBlocks(int numBlocks, long size, String pfx) {
751 return generateFixedBlocks(numBlocks, (int)size, pfx);
752 }
753
754 private CachedItem [] generateRandomBlocks(int numBlocks, long maxSize) {
755 CachedItem [] blocks = new CachedItem[numBlocks];
756 Random r = new Random();
757 for(int i=0;i<numBlocks;i++) {
758 blocks[i] = new CachedItem("block" + i, r.nextInt((int)maxSize)+1);
759 }
760 return blocks;
761 }
762
763 private long calculateBlockSize(long maxSize, int numBlocks) {
764 long roughBlockSize = maxSize / numBlocks;
765 int numEntries = (int)Math.ceil((1.2)*maxSize/roughBlockSize);
766 long totalOverhead = LruBlockCache.CACHE_FIXED_OVERHEAD +
767 ClassSize.CONCURRENT_HASHMAP +
768 (numEntries * ClassSize.CONCURRENT_HASHMAP_ENTRY) +
769 (LruBlockCache.DEFAULT_CONCURRENCY_LEVEL * ClassSize.CONCURRENT_HASHMAP_SEGMENT);
770 long negateBlockSize = (long)(totalOverhead/numEntries);
771 negateBlockSize += LruCachedBlock.PER_BLOCK_OVERHEAD;
772 return ClassSize.align((long)Math.floor((roughBlockSize - negateBlockSize)*0.99f));
773 }
774
775 private long calculateBlockSizeDefault(long maxSize, int numBlocks) {
776 long roughBlockSize = maxSize / numBlocks;
777 int numEntries = (int)Math.ceil((1.2)*maxSize/roughBlockSize);
778 long totalOverhead = LruBlockCache.CACHE_FIXED_OVERHEAD +
779 ClassSize.CONCURRENT_HASHMAP +
780 (numEntries * ClassSize.CONCURRENT_HASHMAP_ENTRY) +
781 (LruBlockCache.DEFAULT_CONCURRENCY_LEVEL * ClassSize.CONCURRENT_HASHMAP_SEGMENT);
782 long negateBlockSize = totalOverhead / numEntries;
783 negateBlockSize += LruCachedBlock.PER_BLOCK_OVERHEAD;
784 return ClassSize.align((long)Math.floor((roughBlockSize - negateBlockSize)*
785 LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));
786 }
787
788 private static class CachedItem implements Cacheable {
789 BlockCacheKey cacheKey;
790 int size;
791
792 CachedItem(String blockName, int size) {
793 this.cacheKey = new BlockCacheKey(blockName, 0);
794 this.size = size;
795 }
796
797
798 @Override
799 public long heapSize() {
800 return ClassSize.align(size);
801 }
802
803
804 public long cacheBlockHeapSize() {
805 return LruCachedBlock.PER_BLOCK_OVERHEAD
806 + ClassSize.align(cacheKey.heapSize())
807 + ClassSize.align(size);
808 }
809
810 @Override
811 public int getSerializedLength() {
812 return 0;
813 }
814
815 @Override
816 public CacheableDeserializer<Cacheable> getDeserializer() {
817 return null;
818 }
819
820 @Override
821 public void serialize(ByteBuffer destination) {
822 }
823
824 @Override
825 public BlockType getBlockType() {
826 return BlockType.DATA;
827 }
828
829 }
830
831 }
832