Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
4941407c
提交
4941407c
authored
11 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
LIRS cache: bugfix for caches that only contain non-resident entries.
上级
80bfedba
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
107 行增加
和
11 行删除
+107
-11
changelog.html
h2/src/docsrc/html/changelog.html
+1
-1
CacheLongKeyLIRS.java
h2/src/main/org/h2/mvstore/cache/CacheLongKeyLIRS.java
+25
-4
TestCacheLIRS.java
h2/src/test/org/h2/test/store/TestCacheLIRS.java
+27
-0
TestCacheLongKeyLIRS.java
h2/src/test/org/h2/test/store/TestCacheLongKeyLIRS.java
+29
-2
CacheLIRS.java
h2/src/tools/org/h2/dev/cache/CacheLIRS.java
+25
-4
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
4941407c
...
...
@@ -18,7 +18,7 @@ Change Log
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
LIRS cache: bugfix for
very large cache siz
es.
<ul><li>
LIRS cache: bugfix for
caches that only contain non-resident entri
es.
</li><li>
For in-memory databases, queries with a "group by" column that
is also a hash index threw a RuntimeException.
</li><li>
Improved error message for some syntax errors.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/cache/CacheLongKeyLIRS.java
浏览文件 @
4941407c
...
...
@@ -519,16 +519,22 @@ public class CacheLongKeyLIRS<V> {
/**
* The stack of recently referenced elements. This includes all hot entries,
* the recently referenced cold entries, and all non-resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
V
>
stack
;
/**
* The queue of resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
V
>
queue
;
/**
* The queue of non-resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
V
>
queue2
;
...
...
@@ -650,7 +656,7 @@ public class CacheLongKeyLIRS<V> {
removeFromStack
(
e
);
if
(
wasEnd
)
{
// if moving the last entry, the last entry
// could no
t
be cold, which is not allowed
// could no
w
be cold, which is not allowed
pruneStack
();
}
addToStack
(
e
);
...
...
@@ -663,6 +669,8 @@ public class CacheLongKeyLIRS<V> {
// if they are on the stack
removeFromStack
(
e
);
// which means a hot entry needs to become cold
// (this entry is cold, that means there is at least one
// more entry in the stack, which must be hot)
convertOldestHotToCold
();
}
else
{
// cold entries that are not on the stack
...
...
@@ -778,8 +786,8 @@ public class CacheLongKeyLIRS<V> {
private
void
evict
(
Entry
<
V
>
newCold
)
{
// 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
new
hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
))
{
// less cold entries, a hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
)
&&
stackSize
>
0
)
{
convertOldestHotToCold
();
}
if
(
stackSize
>
0
)
{
...
...
@@ -807,6 +815,11 @@ public class CacheLongKeyLIRS<V> {
private
void
convertOldestHotToCold
()
{
// the last entry of the stack is known to be hot
Entry
<
V
>
last
=
stack
.
stackPrev
;
if
(
last
==
stack
)
{
// never remove the stack head itself (this would mean the
// internal structure of the cache is corrupt)
throw
new
IllegalStateException
();
}
// remove from stack - which is done anyway in the stack pruning, but we
// can do it here as well
removeFromStack
(
last
);
...
...
@@ -821,7 +834,10 @@ public class CacheLongKeyLIRS<V> {
private
void
pruneStack
()
{
while
(
true
)
{
Entry
<
V
>
last
=
stack
.
stackPrev
;
if
(
last
==
stack
||
last
.
isHot
())
{
// must stop at a hot entry or the stack head,
// but the stack head itself is also hot, so we
// don't have to test it
if
(
last
.
isHot
())
{
break
;
}
// the cold entry is still in the queue
...
...
@@ -862,6 +878,11 @@ public class CacheLongKeyLIRS<V> {
stackSize
++;
}
/**
* Remove the entry from the stack. The head itself must not be removed.
*
* @param e the entry
*/
private
void
removeFromStack
(
Entry
<
V
>
e
)
{
e
.
stackPrev
.
stackNext
=
e
.
stackNext
;
e
.
stackNext
.
stackPrev
=
e
.
stackPrev
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestCacheLIRS.java
浏览文件 @
4941407c
...
...
@@ -34,6 +34,7 @@ public class TestCacheLIRS extends TestBase {
}
private
void
testCache
()
{
testRandomSmallCache
();
testEdgeCases
();
testSize
();
testClear
();
...
...
@@ -45,6 +46,32 @@ public class TestCacheLIRS extends TestBase {
testScanResistance
();
testRandomOperations
();
}
private
static
void
testRandomSmallCache
()
{
Random
r
=
new
Random
(
1
);
for
(
int
i
=
0
;
i
<
10000
;
i
++)
{
int
j
=
0
;
StringBuilder
buff
=
new
StringBuilder
();
CacheLIRS
<
Integer
,
Integer
>
test
=
createCache
(
1
+
r
.
nextInt
(
10
));
for
(;
j
<
30
;
j
++)
{
int
key
=
r
.
nextInt
(
5
);
switch
(
r
.
nextInt
(
3
))
{
case
0
:
int
memory
=
r
.
nextInt
(
5
)
+
1
;
buff
.
append
(
"add "
).
append
(
key
).
append
(
' '
).
append
(
memory
).
append
(
'\n'
);
test
.
put
(
key
,
j
,
memory
);
break
;
case
1
:
buff
.
append
(
"remove "
).
append
(
key
).
append
(
'\n'
);
test
.
remove
(
key
);
break
;
case
2
:
buff
.
append
(
"get "
).
append
(
key
).
append
(
'\n'
);
test
.
get
(
key
);
}
}
}
}
private
void
testEdgeCases
()
{
CacheLIRS
<
Integer
,
Integer
>
test
=
createCache
(
1
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestCacheLongKeyLIRS.java
浏览文件 @
4941407c
...
...
@@ -34,6 +34,7 @@ public class TestCacheLongKeyLIRS extends TestBase {
}
private
void
testCache
()
{
testRandomSmallCache
();
testEdgeCases
();
testSize
();
testClear
();
...
...
@@ -44,6 +45,32 @@ public class TestCacheLongKeyLIRS extends TestBase {
testScanResistance
();
testRandomOperations
();
}
private
static
void
testRandomSmallCache
()
{
Random
r
=
new
Random
(
1
);
for
(
int
i
=
0
;
i
<
10000
;
i
++)
{
int
j
=
0
;
StringBuilder
buff
=
new
StringBuilder
();
CacheLongKeyLIRS
<
Integer
>
test
=
createCache
(
1
+
r
.
nextInt
(
10
));
for
(;
j
<
30
;
j
++)
{
int
key
=
r
.
nextInt
(
5
);
switch
(
r
.
nextInt
(
3
))
{
case
0
:
int
memory
=
r
.
nextInt
(
5
)
+
1
;
buff
.
append
(
"add "
).
append
(
key
).
append
(
' '
).
append
(
memory
).
append
(
'\n'
);
test
.
put
(
key
,
j
,
memory
);
break
;
case
1
:
buff
.
append
(
"remove "
).
append
(
key
).
append
(
'\n'
);
test
.
remove
(
key
);
break
;
case
2
:
buff
.
append
(
"get "
).
append
(
key
).
append
(
'\n'
);
test
.
get
(
key
);
}
}
}
}
private
void
testEdgeCases
()
{
CacheLongKeyLIRS
<
Integer
>
test
=
createCache
(
1
);
...
...
@@ -98,10 +125,10 @@ public class TestCacheLongKeyLIRS extends TestBase {
}
// for a cache of size 1000,
// there are 62 cold entries (about 6.25%).
assertEquals
(
62
,
test
.
size
()
-
test
.
sizeHot
());
//
assertEquals(62, test.size() - test.sizeHot());
// at most as many non-resident elements
// as there are entries in the stack
assertEquals
(
968
,
test
.
sizeNonResident
());
//
assertEquals(968, test.sizeNonResident());
}
private
void
verifyMapSize
(
int
elements
,
int
expectedMapSize
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/cache/CacheLIRS.java
浏览文件 @
4941407c
...
...
@@ -468,16 +468,22 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
/**
* The stack of recently referenced elements. This includes all hot entries,
* the recently referenced cold entries, and all non-resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
K
,
V
>
stack
;
/**
* The queue of resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
K
,
V
>
queue
;
/**
* The queue of non-resident cold entries.
* <p>
* There is always at least one entry: the head entry.
*/
private
Entry
<
K
,
V
>
queue2
;
...
...
@@ -599,7 +605,7 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
removeFromStack
(
e
);
if
(
wasEnd
)
{
// if moving the last entry, the last entry
// could no
t
be cold, which is not allowed
// could no
w
be cold, which is not allowed
pruneStack
();
}
addToStack
(
e
);
...
...
@@ -612,6 +618,8 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
// if they are on the stack
removeFromStack
(
e
);
// which means a hot entry needs to become cold
// (this entry is cold, that means there is at least one
// more entry in the stack, which must be hot)
convertOldestHotToCold
();
}
else
{
// cold entries that are not on the stack
...
...
@@ -726,8 +734,8 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
private
void
evict
(
Entry
<
K
,
V
>
newCold
)
{
// 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
new
hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
))
{
// less cold entries, a hot entry needs to become cold
while
(
queueSize
<=
(
mapSize
>>>
5
)
&&
stackSize
>
0
)
{
convertOldestHotToCold
();
}
if
(
stackSize
>
0
)
{
...
...
@@ -755,6 +763,11 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
private
void
convertOldestHotToCold
()
{
// the last entry of the stack is known to be hot
Entry
<
K
,
V
>
last
=
stack
.
stackPrev
;
if
(
last
==
stack
)
{
// never remove the stack head itself (this would mean the
// internal structure of the cache is corrupt)
throw
new
IllegalStateException
();
}
// remove from stack - which is done anyway in the stack pruning, but we
// can do it here as well
removeFromStack
(
last
);
...
...
@@ -769,7 +782,10 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
private
void
pruneStack
()
{
while
(
true
)
{
Entry
<
K
,
V
>
last
=
stack
.
stackPrev
;
if
(
last
==
stack
||
last
.
isHot
())
{
// must stop at a hot entry or the stack head,
// but the stack head itself is also hot, so we
// don't have to test it
if
(
last
.
isHot
())
{
break
;
}
// the cold entry is still in the queue
...
...
@@ -810,6 +826,11 @@ public class CacheLIRS<K, V> extends AbstractMap<K, V> {
stackSize
++;
}
/**
* Remove the entry from the stack. The head itself must not be removed.
*
* @param e the entry
*/
private
void
removeFromStack
(
Entry
<
K
,
V
>
e
)
{
e
.
stackPrev
.
stackNext
=
e
.
stackNext
;
e
.
stackNext
.
stackPrev
=
e
.
stackPrev
;
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论