Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
ac41cd11
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ac41cd11
编写于
11月 19, 2017
作者:
D
Dirk Baeumer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement LRU Cache on Linked Map
上级
1b775259
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
263 addition
and
22 deletion
+263
-22
src/vs/base/common/map.ts
src/vs/base/common/map.ts
+85
-18
src/vs/base/test/common/map.test.ts
src/vs/base/test/common/map.test.ts
+175
-1
src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts
...rkbench/parts/tasks/electron-browser/task.contribution.ts
+1
-1
src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts
...kbench/parts/tasks/electron-browser/terminalTaskSystem.ts
+2
-2
未找到文件。
src/vs/base/common/map.ts
浏览文件 @
ac41cd11
...
...
@@ -37,6 +37,7 @@ export function getOrSet<K, V>(map: Map<K, V>, key: K, value: V): V {
}
export
interface
ISerializedBoundedLinkedMap
<
T
>
{
version
?:
string
;
entries
:
{
key
:
string
;
value
:
T
}[];
}
...
...
@@ -621,14 +622,12 @@ interface Item<K, V> {
value
:
V
;
}
export
namespace
Touch
{
export
const
None
:
0
=
0
;
export
const
First
:
1
=
1
;
export
const
Last
:
2
=
2
;
export
enum
Touch
{
None
=
0
,
AsOld
=
1
,
AsNew
=
2
}
export
type
Touch
=
0
|
1
|
2
;
export
class
LinkedMap
<
K
,
V
>
{
private
_map
:
Map
<
K
,
Item
<
K
,
V
>>
;
...
...
@@ -662,11 +661,14 @@ export class LinkedMap<K, V> {
return
this
.
_map
.
has
(
key
);
}
public
get
(
key
:
K
):
V
|
undefined
{
public
get
(
key
:
K
,
touch
:
Touch
=
Touch
.
None
):
V
|
undefined
{
const
item
=
this
.
_map
.
get
(
key
);
if
(
!
item
)
{
return
undefined
;
}
if
(
touch
!==
Touch
.
None
)
{
this
.
touch
(
item
,
touch
);
}
return
item
.
value
;
}
...
...
@@ -683,10 +685,10 @@ export class LinkedMap<K, V> {
case
Touch
.
None
:
this
.
addItemLast
(
item
);
break
;
case
Touch
.
First
:
case
Touch
.
AsOld
:
this
.
addItemFirst
(
item
);
break
;
case
Touch
.
Last
:
case
Touch
.
AsNew
:
this
.
addItemLast
(
item
);
break
;
default
:
...
...
@@ -811,6 +813,26 @@ export class LinkedMap<K, V> {
}
*/
protected
trimOld
(
newSize
:
number
)
{
if
(
newSize
>=
this
.
size
)
{
return
;
}
if
(
newSize
===
0
)
{
this
.
clear
();
return
;
}
let
current
=
this
.
_head
;
let
currentSize
=
this
.
size
;
while
(
current
&&
currentSize
>
newSize
)
{
this
.
_map
.
delete
(
current
.
key
);
current
=
current
.
next
;
currentSize
--
;
}
this
.
_head
=
current
;
this
.
_size
=
currentSize
;
current
.
previous
=
void
0
;
}
private
addItemFirst
(
item
:
Item
<
K
,
V
>
):
void
{
// First time Insert
if
(
!
this
.
_head
&&
!
this
.
_tail
)
{
...
...
@@ -839,8 +861,8 @@ export class LinkedMap<K, V> {
private
removeItem
(
item
:
Item
<
K
,
V
>
):
void
{
if
(
item
===
this
.
_head
&&
item
===
this
.
_tail
)
{
this
.
_head
=
undefined
;
this
.
_tail
=
undefined
;
this
.
_head
=
void
0
;
this
.
_tail
=
void
0
;
}
else
if
(
item
===
this
.
_head
)
{
this
.
_head
=
item
.
next
;
...
...
@@ -863,11 +885,11 @@ export class LinkedMap<K, V> {
if
(
!
this
.
_head
||
!
this
.
_tail
)
{
throw
new
Error
(
'
Invalid list
'
);
}
if
((
touch
!==
Touch
.
First
&&
touch
!==
Touch
.
Last
))
{
if
((
touch
!==
Touch
.
AsOld
&&
touch
!==
Touch
.
AsNew
))
{
return
;
}
if
(
touch
===
Touch
.
First
)
{
if
(
touch
===
Touch
.
AsOld
)
{
if
(
item
===
this
.
_head
)
{
return
;
}
...
...
@@ -879,7 +901,7 @@ export class LinkedMap<K, V> {
if
(
item
===
this
.
_tail
)
{
// previous must be defined since item was not head but is tail
// So there are more than on item in the map
previous
!
.
next
=
undefined
;
previous
!
.
next
=
void
0
;
this
.
_tail
=
previous
;
}
else
{
...
...
@@ -889,11 +911,11 @@ export class LinkedMap<K, V> {
}
// Insert the node at head
item
.
previous
=
undefined
;
item
.
previous
=
void
0
;
item
.
next
=
this
.
_head
;
this
.
_head
.
previous
=
item
;
this
.
_head
=
item
;
}
else
if
(
touch
===
Touch
.
Last
)
{
}
else
if
(
touch
===
Touch
.
AsNew
)
{
if
(
item
===
this
.
_tail
)
{
return
;
}
...
...
@@ -905,17 +927,62 @@ export class LinkedMap<K, V> {
if
(
item
===
this
.
_head
)
{
// next must be defined since item was not tail but is head
// So there are more than on item in the map
next
!
.
previous
=
undefined
;
next
!
.
previous
=
void
0
;
this
.
_head
=
next
;
}
else
{
// Both next and previous are not undefined since item was neither head nor tail.
next
!
.
previous
=
previous
;
previous
!
.
next
=
next
;
}
item
.
next
=
undefined
;
item
.
next
=
void
0
;
item
.
previous
=
this
.
_tail
;
this
.
_tail
.
next
=
item
;
this
.
_tail
=
item
;
}
}
}
export
class
LRUCache
<
K
,
V
>
extends
LinkedMap
<
K
,
V
>
{
private
_limit
:
number
;
private
_ratio
:
number
;
constructor
(
limit
:
number
,
ratio
:
number
=
1
)
{
super
();
this
.
_limit
=
limit
;
this
.
_ratio
=
Math
.
min
(
Math
.
max
(
0
,
ratio
),
1
);
}
public
get
limit
():
number
{
return
this
.
_limit
;
}
public
set
limit
(
limit
:
number
)
{
this
.
_limit
=
limit
;
this
.
checkTrim
();
}
public
get
ratio
():
number
{
return
this
.
_ratio
;
}
public
set
ratio
(
ratio
:
number
)
{
this
.
_ratio
=
Math
.
min
(
Math
.
max
(
0
,
ratio
),
1
);
this
.
checkTrim
();
}
public
get
(
key
:
K
):
V
|
undefined
{
return
super
.
get
(
key
,
Touch
.
AsNew
);
}
public
set
(
key
:
K
,
value
:
V
):
void
{
super
.
set
(
key
,
value
,
Touch
.
AsNew
);
this
.
checkTrim
();
}
private
checkTrim
()
{
if
(
this
.
size
>
this
.
_limit
)
{
this
.
trimOld
(
Math
.
round
(
this
.
_limit
*
this
.
_ratio
));
}
}
}
src/vs/base/test/common/map.test.ts
浏览文件 @
ac41cd11
...
...
@@ -6,12 +6,186 @@
'
use strict
'
;
import
{
BoundedMap
,
ResourceMap
,
TernarySearchTree
,
PathIterator
,
StringIterator
}
from
'
vs/base/common/map
'
;
import
{
BoundedMap
,
ResourceMap
,
TernarySearchTree
,
PathIterator
,
StringIterator
,
LinkedMap
,
Touch
,
LRUCache
}
from
'
vs/base/common/map
'
;
import
*
as
assert
from
'
assert
'
;
import
URI
from
'
vs/base/common/uri
'
;
suite
(
'
Map
'
,
()
=>
{
test
(
'
LinkedMap - Simple
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
bk
'
,
'
bv
'
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
ak
'
,
'
bk
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
av
'
,
'
bv
'
]);
});
test
(
'
LinkedMap - Touch Old one
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
ak
'
,
'
av
'
,
Touch
.
AsOld
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
ak
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
av
'
]);
});
test
(
'
LinkedMap - Touch New one
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
ak
'
,
'
av
'
,
Touch
.
AsNew
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
ak
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
av
'
]);
});
test
(
'
LinkedMap - Touch Old two
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
bk
'
,
'
bv
'
);
map
.
set
(
'
bk
'
,
'
bv
'
,
Touch
.
AsOld
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
bk
'
,
'
ak
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
bv
'
,
'
av
'
]);
});
test
(
'
LinkedMap - Touch New two
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
bk
'
,
'
bv
'
);
map
.
set
(
'
ak
'
,
'
av
'
,
Touch
.
AsNew
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
bk
'
,
'
ak
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
bv
'
,
'
av
'
]);
});
test
(
'
LinkedMap - Touch Old from middle
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
bk
'
,
'
bv
'
);
map
.
set
(
'
ck
'
,
'
cv
'
);
map
.
set
(
'
bk
'
,
'
bv
'
,
Touch
.
AsOld
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
bk
'
,
'
ak
'
,
'
ck
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
bv
'
,
'
av
'
,
'
cv
'
]);
});
test
(
'
LinkedMap - Touch New from middle
'
,
()
=>
{
let
map
=
new
LinkedMap
<
string
,
string
>
();
map
.
set
(
'
ak
'
,
'
av
'
);
map
.
set
(
'
bk
'
,
'
bv
'
);
map
.
set
(
'
ck
'
,
'
cv
'
);
map
.
set
(
'
bk
'
,
'
bv
'
,
Touch
.
AsNew
);
assert
.
deepStrictEqual
(
map
.
keys
(),
[
'
ak
'
,
'
ck
'
,
'
bk
'
]);
assert
.
deepStrictEqual
(
map
.
values
(),
[
'
av
'
,
'
cv
'
,
'
bv
'
]);
});
test
(
'
LinkedMap - basics
'
,
function
()
{
const
map
=
new
LinkedMap
<
string
,
any
>
();
assert
.
equal
(
map
.
size
,
0
);
map
.
set
(
'
1
'
,
1
);
map
.
set
(
'
2
'
,
'
2
'
);
map
.
set
(
'
3
'
,
true
);
const
obj
=
Object
.
create
(
null
);
map
.
set
(
'
4
'
,
obj
);
const
date
=
Date
.
now
();
map
.
set
(
'
5
'
,
date
);
assert
.
equal
(
map
.
size
,
5
);
assert
.
equal
(
map
.
get
(
'
1
'
),
1
);
assert
.
equal
(
map
.
get
(
'
2
'
),
'
2
'
);
assert
.
equal
(
map
.
get
(
'
3
'
),
true
);
assert
.
equal
(
map
.
get
(
'
4
'
),
obj
);
assert
.
equal
(
map
.
get
(
'
5
'
),
date
);
assert
.
ok
(
!
map
.
get
(
'
6
'
));
map
.
delete
(
'
6
'
);
assert
.
equal
(
map
.
size
,
5
);
assert
.
equal
(
map
.
delete
(
'
1
'
),
true
);
assert
.
equal
(
map
.
delete
(
'
2
'
),
true
);
assert
.
equal
(
map
.
delete
(
'
3
'
),
true
);
assert
.
equal
(
map
.
delete
(
'
4
'
),
true
);
assert
.
equal
(
map
.
delete
(
'
5
'
),
true
);
assert
.
equal
(
map
.
size
,
0
);
assert
.
ok
(
!
map
.
get
(
'
5
'
));
assert
.
ok
(
!
map
.
get
(
'
4
'
));
assert
.
ok
(
!
map
.
get
(
'
3
'
));
assert
.
ok
(
!
map
.
get
(
'
2
'
));
assert
.
ok
(
!
map
.
get
(
'
1
'
));
map
.
set
(
'
1
'
,
1
);
map
.
set
(
'
2
'
,
'
2
'
);
map
.
set
(
'
3
'
,
true
);
assert
.
ok
(
map
.
has
(
'
1
'
));
assert
.
equal
(
map
.
get
(
'
1
'
),
1
);
assert
.
equal
(
map
.
get
(
'
2
'
),
'
2
'
);
assert
.
equal
(
map
.
get
(
'
3
'
),
true
);
map
.
clear
();
assert
.
equal
(
map
.
size
,
0
);
assert
.
ok
(
!
map
.
get
(
'
1
'
));
assert
.
ok
(
!
map
.
get
(
'
2
'
));
assert
.
ok
(
!
map
.
get
(
'
3
'
));
assert
.
ok
(
!
map
.
has
(
'
1
'
));
});
test
(
'
LinkedMap - LRUCache simple
'
,
()
=>
{
const
cache
=
new
LRUCache
<
number
,
number
>
(
5
);
[
1
,
2
,
3
,
4
,
5
].
forEach
(
value
=>
cache
.
set
(
value
,
value
));
assert
.
strictEqual
(
cache
.
size
,
5
);
cache
.
set
(
6
,
6
);
assert
.
strictEqual
(
cache
.
size
,
5
);
assert
.
deepStrictEqual
(
cache
.
keys
(),
[
2
,
3
,
4
,
5
,
6
]);
cache
.
set
(
7
,
7
);
assert
.
strictEqual
(
cache
.
size
,
5
);
assert
.
deepStrictEqual
(
cache
.
keys
(),
[
3
,
4
,
5
,
6
,
7
]);
let
values
:
number
[]
=
[];
[
3
,
4
,
5
,
6
,
7
].
forEach
(
key
=>
values
.
push
(
cache
.
get
(
key
)));
assert
.
deepStrictEqual
(
values
,
[
3
,
4
,
5
,
6
,
7
]);
});
test
(
'
LinkedMap - LRU Cache limit
'
,
()
=>
{
const
cache
=
new
LRUCache
<
number
,
number
>
(
10
);
for
(
let
i
=
1
;
i
<=
10
;
i
++
)
{
cache
.
set
(
i
,
i
);
}
assert
.
strictEqual
(
cache
.
size
,
10
);
cache
.
limit
=
5
;
assert
.
strictEqual
(
cache
.
size
,
5
);
assert
.
deepStrictEqual
(
cache
.
keys
(),
[
6
,
7
,
8
,
9
,
10
]);
cache
.
limit
=
20
;
assert
.
strictEqual
(
cache
.
size
,
5
);
for
(
let
i
=
11
;
i
<=
20
;
i
++
)
{
cache
.
set
(
i
,
i
);
}
assert
.
deepEqual
(
cache
.
size
,
15
);
let
values
:
number
[]
=
[];
for
(
let
i
=
6
;
i
<=
20
;
i
++
)
{
values
.
push
(
cache
.
get
(
i
));
assert
.
strictEqual
(
cache
.
get
(
i
),
i
);
}
assert
.
deepStrictEqual
(
cache
.
values
(),
values
);
});
test
(
'
LinkedMap - LRU Cache limit with ration
'
,
()
=>
{
const
cache
=
new
LRUCache
<
number
,
number
>
(
10
,
0.5
);
for
(
let
i
=
1
;
i
<=
10
;
i
++
)
{
cache
.
set
(
i
,
i
);
}
assert
.
strictEqual
(
cache
.
size
,
10
);
cache
.
set
(
11
,
11
);
assert
.
strictEqual
(
cache
.
size
,
5
);
assert
.
deepStrictEqual
(
cache
.
keys
(),
[
7
,
8
,
9
,
10
,
11
]);
let
values
:
number
[]
=
[];
cache
.
keys
().
forEach
(
key
=>
values
.
push
(
cache
.
get
(
key
)));
assert
.
deepStrictEqual
(
values
,
[
7
,
8
,
9
,
10
,
11
]);
assert
.
deepStrictEqual
(
cache
.
values
(),
values
);
});
test
(
'
BoundedMap - basics
'
,
function
()
{
const
map
=
new
BoundedMap
<
any
>
();
...
...
src/vs/workbench/parts/tasks/electron-browser/task.contribution.ts
浏览文件 @
ac41cd11
...
...
@@ -1188,7 +1188,7 @@ class TaskService implements ITaskService {
let
executeResult
=
this
.
getTaskSystem
().
run
(
task
,
resolver
);
let
key
=
Task
.
getRecentlyUsedKey
(
task
);
if
(
key
)
{
this
.
getRecentlyUsedTasks
().
set
(
key
,
key
,
Touch
.
First
);
this
.
getRecentlyUsedTasks
().
set
(
key
,
key
,
Touch
.
AsOld
);
}
if
(
executeResult
.
kind
===
TaskExecuteKind
.
Active
)
{
let
active
=
executeResult
.
active
;
...
...
src/vs/workbench/parts/tasks/electron-browser/terminalTaskSystem.ts
浏览文件 @
ac41cd11
...
...
@@ -280,7 +280,7 @@ export class TerminalTaskSystem implements ITaskSystem {
this
.
sameTaskTerminals
[
key
]
=
terminal
.
id
.
toString
();
break
;
case
PanelKind
.
Shared
:
this
.
idleTaskTerminals
.
set
(
key
,
terminal
.
id
.
toString
(),
Touch
.
First
);
this
.
idleTaskTerminals
.
set
(
key
,
terminal
.
id
.
toString
(),
Touch
.
AsOld
);
break
;
}
watchingProblemMatcher
.
done
();
...
...
@@ -322,7 +322,7 @@ export class TerminalTaskSystem implements ITaskSystem {
this
.
sameTaskTerminals
[
key
]
=
terminal
.
id
.
toString
();
break
;
case
PanelKind
.
Shared
:
this
.
idleTaskTerminals
.
set
(
key
,
terminal
.
id
.
toString
(),
Touch
.
First
);
this
.
idleTaskTerminals
.
set
(
key
,
terminal
.
id
.
toString
(),
Touch
.
AsOld
);
break
;
}
startStopProblemMatcher
.
done
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录