提交 1c75fd78 authored 作者: Thomas Mueller Graf's avatar Thomas Mueller Graf

LIRS cache: keep more non-resident entries

上级 11ef3490
...@@ -55,7 +55,7 @@ public class CacheLongKeyLIRS<V> { ...@@ -55,7 +55,7 @@ public class CacheLongKeyLIRS<V> {
private final int segmentShift; private final int segmentShift;
private final int segmentMask; private final int segmentMask;
private final int stackMoveDistance; private final int stackMoveDistance;
private final double nonResidentQueueSize; private final int nonResidentQueueSize;
/** /**
* Create a new cache with the given memory size. * Create a new cache with the given memory size.
...@@ -535,7 +535,7 @@ public class CacheLongKeyLIRS<V> { ...@@ -535,7 +535,7 @@ public class CacheLongKeyLIRS<V> {
* The number of entries in the non-resident queue, as a factor of the * The number of entries in the non-resident queue, as a factor of the
* number of entries in the map. * number of entries in the map.
*/ */
private final double nonResidentQueueSize; private final int nonResidentQueueSize;
/** /**
* The stack of recently referenced elements. This includes all hot * The stack of recently referenced elements. This includes all hot
...@@ -581,7 +581,7 @@ public class CacheLongKeyLIRS<V> { ...@@ -581,7 +581,7 @@ public class CacheLongKeyLIRS<V> {
* @param nonResidentQueueSize the non-resident queue size factor * @param nonResidentQueueSize the non-resident queue size factor
*/ */
Segment(long maxMemory, int stackMoveDistance, int len, Segment(long maxMemory, int stackMoveDistance, int len,
double nonResidentQueueSize) { int nonResidentQueueSize) {
setMaxMemory(maxMemory); setMaxMemory(maxMemory);
this.stackMoveDistance = stackMoveDistance; this.stackMoveDistance = stackMoveDistance;
this.nonResidentQueueSize = nonResidentQueueSize; this.nonResidentQueueSize = nonResidentQueueSize;
...@@ -904,7 +904,8 @@ public class CacheLongKeyLIRS<V> { ...@@ -904,7 +904,8 @@ public class CacheLongKeyLIRS<V> {
e.memory = 0; e.memory = 0;
addToQueue(queue2, e); addToQueue(queue2, e);
// the size of the non-resident-cold entries needs to be limited // the size of the non-resident-cold entries needs to be limited
int maxQueue2Size = (int) (nonResidentQueueSize * mapSize); int maxQueue2Size = nonResidentQueueSize * (mapSize - queue2Size);
if (maxQueue2Size >= 0) {
while (queue2Size > maxQueue2Size) { while (queue2Size > maxQueue2Size) {
e = queue2.queuePrev; e = queue2.queuePrev;
int hash = getHash(e.key); int hash = getHash(e.key);
...@@ -912,6 +913,7 @@ public class CacheLongKeyLIRS<V> { ...@@ -912,6 +913,7 @@ public class CacheLongKeyLIRS<V> {
} }
} }
} }
}
private void convertOldestHotToCold() { private void convertOldestHotToCold() {
// the last entry of the stack is known to be hot // the last entry of the stack is known to be hot
...@@ -1165,15 +1167,16 @@ public class CacheLongKeyLIRS<V> { ...@@ -1165,15 +1167,16 @@ public class CacheLongKeyLIRS<V> {
public int segmentCount = 16; public int segmentCount = 16;
/** /**
* How many other item are to be moved to the top of the stack before the current item is moved. * How many other item are to be moved to the top of the stack before
* the current item is moved.
*/ */
public int stackMoveDistance = 32; public int stackMoveDistance = 32;
/** /**
* The number of entries in the non-resident queue, as a factor of the * The number of entries in the non-resident queue, as a factor of the
* number of entries in the map. * number of all other entries in the map.
*/ */
public double nonResidentQueueSize = 0.5; public int nonResidentQueueSize = 3;
} }
......
...@@ -114,7 +114,8 @@ public class TestCacheLongKeyLIRS extends TestBase { ...@@ -114,7 +114,8 @@ public class TestCacheLongKeyLIRS extends TestBase {
assertEquals(63, test.size() - test.sizeHot()); assertEquals(63, test.size() - test.sizeHot());
// at most as many non-resident elements // at most as many non-resident elements
// as there are entries in the stack // as there are entries in the stack
assertEquals(999, test.sizeNonResident()); assertEquals(1000, test.size());
assertEquals(1000, test.sizeNonResident());
} }
private void verifyMapSize(int elements, int expectedMapSize) { private void verifyMapSize(int elements, int expectedMapSize) {
...@@ -323,8 +324,8 @@ public class TestCacheLongKeyLIRS extends TestBase { ...@@ -323,8 +324,8 @@ public class TestCacheLongKeyLIRS extends TestBase {
test.put(i, 10 * i); test.put(i, 10 * i);
} }
assertEquals(100, test.size()); assertEquals(100, test.size());
assertEquals(99, test.sizeNonResident()); assertEquals(200, test.sizeNonResident());
assertEquals(93, test.sizeHot()); assertEquals(90, test.sizeHot());
} }
private void testLimitNonResident() { private void testLimitNonResident() {
...@@ -332,8 +333,8 @@ public class TestCacheLongKeyLIRS extends TestBase { ...@@ -332,8 +333,8 @@ public class TestCacheLongKeyLIRS extends TestBase {
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
test.put(i, 10 * i); test.put(i, 10 * i);
} }
verify(test, "mem: 4 stack: 19 18 17 16 3 2 1 " + verify(test, "mem: 4 stack: 19 18 17 16 15 14 13 12 11 10 3 2 1 " +
"cold: 19 non-resident: 18 17 16"); "cold: 19 non-resident: 18 17 16 15 14 13 12 11 10");
} }
private void testLimitMemory() { private void testLimitMemory() {
...@@ -344,21 +345,21 @@ public class TestCacheLongKeyLIRS extends TestBase { ...@@ -344,21 +345,21 @@ public class TestCacheLongKeyLIRS extends TestBase {
verify(test, "mem: 4 stack: 4 3 2 1 cold: 4 non-resident: 0"); verify(test, "mem: 4 stack: 4 3 2 1 cold: 4 non-resident: 0");
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4); assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
test.put(6, 60, 3); test.put(6, 60, 3);
verify(test, "mem: 4 stack: 6 3 cold: 6 non-resident: 2 1"); verify(test, "mem: 4 stack: 6 4 3 cold: 6 non-resident: 2 1 4");
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4); assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
test.put(7, 70, 3); test.put(7, 70, 3);
verify(test, "mem: 4 stack: 7 6 3 cold: 7 non-resident: 6 2"); verify(test, "mem: 4 stack: 7 6 3 cold: 7 non-resident: 6 2 1");
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4); assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
test.put(8, 80, 4); test.put(8, 80, 4);
verify(test, "mem: 4 stack: 8 cold: non-resident: 3"); verify(test, "mem: 4 stack: 8 cold: non-resident:");
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4); assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
} }
private void testScanResistance() { private void testScanResistance() {
boolean log = false; boolean log = false;
int size = 20; int size = 20;
// cache size 11 (10 hot, 1 cold) // cache size 11 (10 hot, 2 cold)
CacheLongKeyLIRS<Integer> test = createCache(size / 2 + 1); CacheLongKeyLIRS<Integer> test = createCache(size / 2 + 2);
// init the cache with some dummy entries // init the cache with some dummy entries
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
test.put(-i, -i * 10); test.put(-i, -i * 10);
...@@ -394,10 +395,10 @@ public class TestCacheLongKeyLIRS extends TestBase { ...@@ -394,10 +395,10 @@ public class TestCacheLongKeyLIRS extends TestBase {
} }
verify(test, null); verify(test, null);
} }
// ensure 0..9 are hot, 10..18 are not resident, 19 is cold // ensure 0..9 are hot, 10..17 are not resident, 18..19 are cold
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Integer x = test.get(i); Integer x = test.get(i);
if (i < size / 2 || i == size - 1) { if (i < size / 2 || i == size - 1 || i == size - 2) {
assertTrue("i: " + i, x != null); assertTrue("i: " + i, x != null);
assertEquals(i * 10, x.intValue()); assertEquals(i * 10, x.intValue());
} else { } else {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论