Skip to content

Commit 1c75fd7

Browse files
committed
LIRS cache: keep more non-resident entries
1 parent 11ef349 commit 1c75fd7

File tree

2 files changed

+27
-23
lines changed

2 files changed

+27
-23
lines changed

h2/src/main/org/h2/mvstore/cache/CacheLongKeyLIRS.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class CacheLongKeyLIRS<V> {
5555
private final int segmentShift;
5656
private final int segmentMask;
5757
private final int stackMoveDistance;
58-
private final double nonResidentQueueSize;
58+
private final int nonResidentQueueSize;
5959

6060
/**
6161
* Create a new cache with the given memory size.
@@ -535,7 +535,7 @@ private static class Segment<V> {
535535
* The number of entries in the non-resident queue, as a factor of the
536536
* number of entries in the map.
537537
*/
538-
private final double nonResidentQueueSize;
538+
private final int nonResidentQueueSize;
539539

540540
/**
541541
* The stack of recently referenced elements. This includes all hot
@@ -581,7 +581,7 @@ private static class Segment<V> {
581581
* @param nonResidentQueueSize the non-resident queue size factor
582582
*/
583583
Segment(long maxMemory, int stackMoveDistance, int len,
584-
double nonResidentQueueSize) {
584+
int nonResidentQueueSize) {
585585
setMaxMemory(maxMemory);
586586
this.stackMoveDistance = stackMoveDistance;
587587
this.nonResidentQueueSize = nonResidentQueueSize;
@@ -904,11 +904,13 @@ private void evictBlock() {
904904
e.memory = 0;
905905
addToQueue(queue2, e);
906906
// the size of the non-resident-cold entries needs to be limited
907-
int maxQueue2Size = (int) (nonResidentQueueSize * mapSize);
908-
while (queue2Size > maxQueue2Size) {
909-
e = queue2.queuePrev;
910-
int hash = getHash(e.key);
911-
remove(e.key, hash);
907+
int maxQueue2Size = nonResidentQueueSize * (mapSize - queue2Size);
908+
if (maxQueue2Size >= 0) {
909+
while (queue2Size > maxQueue2Size) {
910+
e = queue2.queuePrev;
911+
int hash = getHash(e.key);
912+
remove(e.key, hash);
913+
}
912914
}
913915
}
914916
}
@@ -1165,15 +1167,16 @@ public static class Config {
11651167
public int segmentCount = 16;
11661168

11671169
/**
1168-
* How many other item are to be moved to the top of the stack before the current item is moved.
1170+
* How many other item are to be moved to the top of the stack before
1171+
* the current item is moved.
11691172
*/
11701173
public int stackMoveDistance = 32;
11711174

11721175
/**
11731176
* The number of entries in the non-resident queue, as a factor of the
1174-
* number of entries in the map.
1177+
* number of all other entries in the map.
11751178
*/
1176-
public double nonResidentQueueSize = 0.5;
1179+
public int nonResidentQueueSize = 3;
11771180

11781181
}
11791182

h2/src/test/org/h2/test/store/TestCacheLongKeyLIRS.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ private void testSize() {
114114
assertEquals(63, test.size() - test.sizeHot());
115115
// at most as many non-resident elements
116116
// as there are entries in the stack
117-
assertEquals(999, test.sizeNonResident());
117+
assertEquals(1000, test.size());
118+
assertEquals(1000, test.sizeNonResident());
118119
}
119120

120121
private void verifyMapSize(int elements, int expectedMapSize) {
@@ -323,17 +324,17 @@ private void testLimitHot() {
323324
test.put(i, 10 * i);
324325
}
325326
assertEquals(100, test.size());
326-
assertEquals(99, test.sizeNonResident());
327-
assertEquals(93, test.sizeHot());
327+
assertEquals(200, test.sizeNonResident());
328+
assertEquals(90, test.sizeHot());
328329
}
329330

330331
private void testLimitNonResident() {
331332
CacheLongKeyLIRS<Integer> test = createCache(4);
332333
for (int i = 0; i < 20; i++) {
333334
test.put(i, 10 * i);
334335
}
335-
verify(test, "mem: 4 stack: 19 18 17 16 3 2 1 " +
336-
"cold: 19 non-resident: 18 17 16");
336+
verify(test, "mem: 4 stack: 19 18 17 16 15 14 13 12 11 10 3 2 1 " +
337+
"cold: 19 non-resident: 18 17 16 15 14 13 12 11 10");
337338
}
338339

339340
private void testLimitMemory() {
@@ -344,21 +345,21 @@ private void testLimitMemory() {
344345
verify(test, "mem: 4 stack: 4 3 2 1 cold: 4 non-resident: 0");
345346
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
346347
test.put(6, 60, 3);
347-
verify(test, "mem: 4 stack: 6 3 cold: 6 non-resident: 2 1");
348+
verify(test, "mem: 4 stack: 6 4 3 cold: 6 non-resident: 2 1 4");
348349
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
349350
test.put(7, 70, 3);
350-
verify(test, "mem: 4 stack: 7 6 3 cold: 7 non-resident: 6 2");
351+
verify(test, "mem: 4 stack: 7 6 3 cold: 7 non-resident: 6 2 1");
351352
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
352353
test.put(8, 80, 4);
353-
verify(test, "mem: 4 stack: 8 cold: non-resident: 3");
354+
verify(test, "mem: 4 stack: 8 cold: non-resident:");
354355
assertTrue("" + test.getUsedMemory(), test.getUsedMemory() <= 4);
355356
}
356357

357358
private void testScanResistance() {
358359
boolean log = false;
359360
int size = 20;
360-
// cache size 11 (10 hot, 1 cold)
361-
CacheLongKeyLIRS<Integer> test = createCache(size / 2 + 1);
361+
// cache size 11 (10 hot, 2 cold)
362+
CacheLongKeyLIRS<Integer> test = createCache(size / 2 + 2);
362363
// init the cache with some dummy entries
363364
for (int i = 0; i < size; i++) {
364365
test.put(-i, -i * 10);
@@ -394,10 +395,10 @@ private void testScanResistance() {
394395
}
395396
verify(test, null);
396397
}
397-
// ensure 0..9 are hot, 10..18 are not resident, 19 is cold
398+
// ensure 0..9 are hot, 10..17 are not resident, 18..19 are cold
398399
for (int i = 0; i < size; i++) {
399400
Integer x = test.get(i);
400-
if (i < size / 2 || i == size - 1) {
401+
if (i < size / 2 || i == size - 1 || i == size - 2) {
401402
assertTrue("i: " + i, x != null);
402403
assertEquals(i * 10, x.intValue());
403404
} else {

0 commit comments

Comments
 (0)