Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
d87244fa
提交
d87244fa
authored
10 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
The LIRS cache could grow larger than the allocated memory.
上级
26f02d9c
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
94 行增加
和
38 行删除
+94
-38
CacheLongKeyLIRS.java
h2/src/main/org/h2/mvstore/cache/CacheLongKeyLIRS.java
+27
-18
TestCacheLIRS.java
h2/src/test/org/h2/test/store/TestCacheLIRS.java
+20
-1
TestCacheLongKeyLIRS.java
h2/src/test/org/h2/test/store/TestCacheLongKeyLIRS.java
+20
-1
CacheLIRS.java
h2/src/tools/org/h2/dev/cache/CacheLIRS.java
+27
-18
没有找到文件。
h2/src/main/org/h2/mvstore/cache/CacheLongKeyLIRS.java
浏览文件 @
d87244fa
...
...
@@ -62,7 +62,7 @@ public class CacheLongKeyLIRS<V> {
*
* @param maxMemory the maximum memory to use (1 or larger)
*/
public
CacheLongKeyLIRS
(
int
maxMemory
)
{
public
CacheLongKeyLIRS
(
long
maxMemory
)
{
this
(
maxMemory
,
16
,
8
);
}
...
...
@@ -543,11 +543,6 @@ public class CacheLongKeyLIRS<V> {
*/
private
final
int
mask
;
/**
* The LIRS stack size.
*/
private
int
stackSize
;
/**
* The stack of recently referenced elements. This includes all hot
* entries, and the recently referenced cold entries. Resident cold
...
...
@@ -558,6 +553,11 @@ public class CacheLongKeyLIRS<V> {
*/
private
final
Entry
<
V
>
stack
;
/**
* The number of entries in the stack.
*/
private
int
stackSize
;
/**
* The queue of resident cold entries.
* <p>
...
...
@@ -800,6 +800,10 @@ public class CacheLongKeyLIRS<V> {
old
=
e
.
value
;
remove
(
key
,
hash
);
}
if
(
memory
>
maxMemory
)
{
// the new entry is too big to fit
return
old
;
}
e
=
new
Entry
<
V
>();
e
.
key
=
key
;
e
.
value
=
value
;
...
...
@@ -808,9 +812,15 @@ public class CacheLongKeyLIRS<V> {
e
.
mapNext
=
entries
[
index
];
entries
[
index
]
=
e
;
usedMemory
+=
memory
;
if
(
usedMemory
>
maxMemory
&&
mapSize
>
0
)
{
// an old entry needs to be removed
evict
(
e
);
if
(
usedMemory
>
maxMemory
)
{
// old entries needs to be removed
evict
();
// if the cache is full, the new entry is
// cold if possible
if
(
stackSize
>
0
)
{
// the new cold entry is at the top of the queue
addToQueue
(
queue
,
e
);
}
}
mapSize
++;
// added entries are always added to the stack
...
...
@@ -874,23 +884,22 @@ public class CacheLongKeyLIRS<V> {
* Evict cold entries (resident and non-resident) until the memory limit
* is reached. The new entry is added as a cold entry, except if it is
* the only entry.
*
* @param newCold a new cold entry
*/
private
void
evict
(
Entry
<
V
>
newCold
)
{
private
void
evict
()
{
do
{
evictBlock
();
}
while
(
usedMemory
>
maxMemory
);
}
private
void
evictBlock
()
{
// ensure there are not too many hot entries: right shift of 5 is
// division by 32, that means if there are only 1/32 (3.125%) or
// less cold entries, a hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
)
&&
stackSize
>
0
)
{
convertOldestHotToCold
();
}
if
(
stackSize
>
0
)
{
// the new cold entry is at the top of the queue
addToQueue
(
queue
,
newCold
);
}
// the oldest resident cold entries become non-resident
// but at least one cold entry (the new one) must stay
while
(
usedMemory
>
maxMemory
&&
queueSize
>
1
)
{
while
(
usedMemory
>
maxMemory
&&
queueSize
>
0
)
{
Entry
<
V
>
e
=
queue
.
queuePrev
;
usedMemory
-=
e
.
memory
;
removeFromQueue
(
e
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestCacheLIRS.java
浏览文件 @
d87244fa
...
...
@@ -43,6 +43,7 @@ public class TestCacheLIRS extends TestBase {
testLimitHot
();
testLimitNonResident
();
testBadHashMethod
();
testLimitMemory
();
testScanResistance
();
testRandomOperations
();
}
...
...
@@ -77,7 +78,7 @@ public class TestCacheLIRS extends TestBase {
private
void
testEdgeCases
()
{
CacheLIRS
<
Integer
,
Integer
>
test
=
createCache
(
1
);
test
.
put
(
1
,
10
,
100
);
assertEquals
(
10
,
test
.
get
(
1
).
intValu
e
());
assertEquals
(
0
,
test
.
siz
e
());
try
{
test
.
put
(
null
,
10
,
100
);
fail
();
...
...
@@ -407,6 +408,24 @@ public class TestCacheLIRS extends TestBase {
}
}
private
void
testLimitMemory
()
{
CacheLIRS
<
Integer
,
Integer
>
test
=
createCache
(
4
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
test
.
put
(
i
,
10
*
i
,
1
);
}
verify
(
test
,
"mem: 4 stack: 4 3 2 1 cold: 4 non-resident: 0"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
6
,
60
,
3
);
verify
(
test
,
"mem: 4 stack: 6 3 cold: 6 non-resident:"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
7
,
70
,
3
);
verify
(
test
,
"mem: 4 stack: 7 6 3 cold: 7 non-resident: 6"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
8
,
80
,
4
);
verify
(
test
,
"mem: 4 stack: 8 cold: non-resident:"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
}
private
void
testScanResistance
()
{
boolean
log
=
false
;
int
size
=
20
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestCacheLongKeyLIRS.java
浏览文件 @
d87244fa
...
...
@@ -43,6 +43,7 @@ public class TestCacheLongKeyLIRS extends TestBase {
testPruneStack
();
testLimitHot
();
testLimitNonResident
();
testLimitMemory
();
testScanResistance
();
testRandomOperations
();
}
...
...
@@ -77,7 +78,7 @@ public class TestCacheLongKeyLIRS extends TestBase {
private
void
testEdgeCases
()
{
CacheLongKeyLIRS
<
Integer
>
test
=
createCache
(
1
);
test
.
put
(
1
,
10
,
100
);
assertEquals
(
10
,
test
.
get
(
1
).
intValu
e
());
assertEquals
(
0
,
test
.
siz
e
());
try
{
test
.
put
(
1
,
null
,
100
);
fail
();
...
...
@@ -335,6 +336,24 @@ public class TestCacheLongKeyLIRS extends TestBase {
"cold: 19 non-resident: 18 17 16"
);
}
private
void
testLimitMemory
()
{
CacheLongKeyLIRS
<
Integer
>
test
=
createCache
(
4
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
test
.
put
(
i
,
10
*
i
,
1
);
}
verify
(
test
,
"mem: 4 stack: 4 3 2 1 cold: 4 non-resident: 0"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
6
,
60
,
3
);
verify
(
test
,
"mem: 4 stack: 6 3 cold: 6 non-resident:"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
7
,
70
,
3
);
verify
(
test
,
"mem: 4 stack: 7 6 3 cold: 7 non-resident: 6"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
test
.
put
(
8
,
80
,
4
);
verify
(
test
,
"mem: 4 stack: 8 cold: non-resident:"
);
assertTrue
(
""
+
test
.
getUsedMemory
(),
test
.
getUsedMemory
()
<=
4
);
}
private
void
testScanResistance
()
{
boolean
log
=
false
;
int
size
=
20
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/cache/CacheLIRS.java
浏览文件 @
d87244fa
...
...
@@ -64,7 +64,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
*
* @param maxMemory the maximum memory to use (1 or larger)
*/
public
CacheLIRS
(
int
maxMemory
)
{
public
CacheLIRS
(
long
maxMemory
)
{
this
(
maxMemory
,
16
,
8
);
}
...
...
@@ -470,11 +470,6 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
*/
private
final
int
mask
;
/**
* The LIRS stack size.
*/
private
int
stackSize
;
/**
* The stack of recently referenced elements. This includes all hot
* entries, and the recently referenced cold entries. Resident cold
...
...
@@ -485,6 +480,11 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
*/
private
final
Entry
<
K
,
V
>
stack
;
/**
* The number of entries in the stack.
*/
private
int
stackSize
;
/**
* The queue of resident cold entries.
* <p>
...
...
@@ -724,6 +724,10 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
old
=
e
.
value
;
remove
(
key
,
hash
);
}
if
(
memory
>
maxMemory
)
{
// the new entry is too big to fit
return
old
;
}
e
=
new
Entry
<
K
,
V
>();
e
.
key
=
key
;
e
.
value
=
value
;
...
...
@@ -732,9 +736,15 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
e
.
mapNext
=
entries
[
index
];
entries
[
index
]
=
e
;
usedMemory
+=
memory
;
if
(
usedMemory
>
maxMemory
&&
mapSize
>
0
)
{
// an old entry needs to be removed
evict
(
e
);
if
(
usedMemory
>
maxMemory
)
{
// old entries needs to be removed
evict
();
// if the cache is full, the new entry is
// cold if possible
if
(
stackSize
>
0
)
{
// the new cold entry is at the top of the queue
addToQueue
(
queue
,
e
);
}
}
mapSize
++;
// added entries are always added to the stack
...
...
@@ -798,23 +808,22 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
* Evict cold entries (resident and non-resident) until the memory limit
* is reached. The new entry is added as a cold entry, except if it is
* the only entry.
*
* @param newCold a new cold entry
*/
private
void
evict
(
Entry
<
K
,
V
>
newCold
)
{
private
void
evict
()
{
do
{
evictBlock
();
}
while
(
usedMemory
>
maxMemory
);
}
private
void
evictBlock
()
{
// ensure there are not too many hot entries: right shift of 5 is
// division by 32, that means if there are only 1/32 (3.125%) or
// less cold entries, a hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
)
&&
stackSize
>
0
)
{
convertOldestHotToCold
();
}
if
(
stackSize
>
0
)
{
// the new cold entry is at the top of the queue
addToQueue
(
queue
,
newCold
);
}
// the oldest resident cold entries become non-resident
// but at least one cold entry (the new one) must stay
while
(
usedMemory
>
maxMemory
&&
queueSize
>
1
)
{
while
(
usedMemory
>
maxMemory
&&
queueSize
>
0
)
{
Entry
<
K
,
V
>
e
=
queue
.
queuePrev
;
usedMemory
-=
e
.
memory
;
removeFromQueue
(
e
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论