Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Turbo码先生
redis
提交
5792a217
R
redis
项目概览
Turbo码先生
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5792a217
编写于
2月 06, 2015
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dict.c: add dictGetSomeKeys(), specialized for eviction.
上级
f25fdd62
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
95 addition
and
2 deletion
+95
-2
src/dict.c
src/dict.c
+93
-1
src/dict.h
src/dict.h
+1
-0
src/redis.c
src/redis.c
+1
-1
未找到文件。
src/dict.c
浏览文件 @
5792a217
...
...
@@ -664,7 +664,10 @@ dictEntry *dictGetRandomKey(dict *d)
return
he
;
}
/* This is a version of dictGetRandomKey() that is modified in order to
/* XXX: This is going to be removed soon and SPOP internals
* reimplemented.
*
* This is a version of dictGetRandomKey() that is modified in order to
* return multiple entries by jumping at a random place of the hash table
* and scanning linearly for entries.
*
...
...
@@ -735,6 +738,95 @@ unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) {
return
stored
;
/* Never reached. */
}
/* This function samples the dictionary to return a few keys from random
* locations.
*
* It does not guarantee to return all the keys specified in 'count', nor
* it does guarantee to return non-duplicated elements, however it will make
* some effort to do both things.
*
* Returned pointers to hash table entries are stored into 'des' that
* points to an array of dictEntry pointers. The array must have room for
* at least 'count' elements, that is the argument we pass to the function
* to tell how many random elements we need.
*
* The function returns the number of items stored into 'des', that may
* be less than 'count' if the hash table has less than 'count' elements
* inside, or if not enough elements were found in a reasonable amount of
* steps.
*
* Note that this function is not suitable when you need a good distribution
* of the returned items, but only when you need to "sample" a given number
* of continuous elements to run some kind of algorithm or to produce
* statistics. However the function is much faster than dictGetRandomKey()
* at producing N elements. */
unsigned
int
dictGetSomeKeys
(
dict
*
d
,
dictEntry
**
des
,
unsigned
int
count
)
{
unsigned
int
j
;
/* internal hash table id, 0 or 1. */
unsigned
int
tables
;
/* 1 or 2 tables? */
unsigned
int
stored
=
0
,
maxsizemask
;
unsigned
int
maxsteps
;
if
(
dictSize
(
d
)
<
count
)
count
=
dictSize
(
d
);
maxsteps
=
count
*
10
;
/* Try to do a rehashing work proportional to 'count'. */
for
(
j
=
0
;
j
<
count
;
j
++
)
{
if
(
dictIsRehashing
(
d
))
_dictRehashStep
(
d
);
else
break
;
}
tables
=
dictIsRehashing
(
d
)
?
2
:
1
;
maxsizemask
=
d
->
ht
[
0
].
sizemask
;
if
(
tables
>
1
&&
maxsizemask
<
d
->
ht
[
1
].
sizemask
)
maxsizemask
=
d
->
ht
[
1
].
sizemask
;
/* Pick a random point inside the larger table. */
unsigned
int
i
=
random
()
&
maxsizemask
;
unsigned
int
emptylen
=
0
;
/* Continuous empty entries so far. */
while
(
stored
<
count
&&
maxsteps
--
)
{
for
(
j
=
0
;
j
<
tables
;
j
++
)
{
/* Invariant of the dict.c rehashing: up to the indexes already
* visited in ht[0] during the rehashing, there are no populated
* buckets, so we can skip ht[0] for indexes between 0 and idx-1. */
if
(
tables
==
2
&&
j
==
0
&&
i
<
d
->
rehashidx
)
{
/* Moreover, if we are currently out of range in the second
* table, there will be no elements in both tables up to
* the current rehashing index, so we jump if possible.
* (this happens when going from big to small table). */
if
(
i
>=
d
->
ht
[
1
].
size
)
i
=
d
->
rehashidx
;
continue
;
}
if
(
i
>=
d
->
ht
[
j
].
size
)
continue
;
/* Out of range for this table. */
dictEntry
*
he
=
d
->
ht
[
j
].
table
[
i
];
/* Count contiguous empty buckets, and jump to other
* locations if they reach 'count' (with a minimum of 5). */
if
(
he
==
NULL
)
{
emptylen
++
;
if
(
emptylen
>=
5
&&
emptylen
>
count
)
{
i
=
random
()
&
maxsizemask
;
emptylen
=
0
;
}
}
else
{
while
(
he
)
{
/* Collect all the elements of the buckets found non
* empty while iterating. */
*
des
=
he
;
des
++
;
he
=
he
->
next
;
stored
++
;
if
(
stored
==
count
)
return
stored
;
}
}
}
i
=
(
i
+
1
)
&
maxsizemask
;
}
return
stored
;
}
/* Function to reverse bits. Algorithm from:
* http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel */
static
unsigned
long
rev
(
unsigned
long
v
)
{
...
...
src/dict.h
浏览文件 @
5792a217
...
...
@@ -164,6 +164,7 @@ dictIterator *dictGetSafeIterator(dict *d);
dictEntry
*
dictNext
(
dictIterator
*
iter
);
void
dictReleaseIterator
(
dictIterator
*
iter
);
dictEntry
*
dictGetRandomKey
(
dict
*
d
);
unsigned
int
dictGetSomeKeys
(
dict
*
d
,
dictEntry
**
des
,
unsigned
int
count
);
unsigned
int
dictGetRandomKeys
(
dict
*
d
,
dictEntry
**
des
,
unsigned
int
count
);
void
dictPrintStats
(
dict
*
d
);
unsigned
int
dictGenHashFunction
(
const
void
*
key
,
int
len
);
...
...
src/redis.c
浏览文件 @
5792a217
...
...
@@ -3148,7 +3148,7 @@ void evictionPoolPopulate(dict *sampledict, dict *keydict, struct evictionPoolEn
}
#if 1
/* Use bulk get by default. */
count
=
dictGet
Random
Keys
(
sampledict
,
samples
,
server
.
maxmemory_samples
);
count
=
dictGet
Some
Keys
(
sampledict
,
samples
,
server
.
maxmemory_samples
);
#else
count
=
server
.
maxmemory_samples
;
for
(
j
=
0
;
j
<
count
;
j
++
)
samples
[
j
]
=
dictGetRandomKey
(
sampledict
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录