Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hanoi2005
redis
提交
f0eca148
R
redis
项目概览
hanoi2005
/
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,发现更多精彩内容 >>
提交
f0eca148
编写于
4月 17, 2014
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
PFCOUNT support for multi-key union.
上级
d25fd8be
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
73 addition
and
6 deletion
+73
-6
src/hyperloglog.c
src/hyperloglog.c
+72
-5
src/redis.c
src/redis.c
+1
-1
未找到文件。
src/hyperloglog.c
浏览文件 @
f0eca148
...
...
@@ -198,8 +198,9 @@ struct hllhdr {
#define HLL_REGISTER_MAX ((1<<HLL_BITS)-1)
#define HLL_HDR_SIZE sizeof(struct hllhdr)
#define HLL_DENSE_SIZE (HLL_HDR_SIZE+((HLL_REGISTERS*HLL_BITS+7)/8))
#define HLL_DENSE 0
/* Dense encoding */
#define HLL_SPARSE 1
/* Sparse encoding */
#define HLL_DENSE 0
/* Dense encoding. */
#define HLL_SPARSE 1
/* Sparse encoding. */
#define HLL_RAW 255
/* Only used internally, never exposed. */
#define HLL_MAX_ENCODING 1
static
char
*
invalid_hll_err
=
"-INVALIDOBJ Corrupted HLL object detected
\r\n
"
;
...
...
@@ -920,12 +921,37 @@ double hllSparseSum(uint8_t *sparse, int sparselen, double *PE, int *ezp, int *i
* as helpers to compute the SUM(2^-reg) part of the computation, which is
* representation-specific, while all the rest is common. */
/* Implements the SUM operation for uint8_t data type which is only used
* internally as speedup for PFCOUNT with multiple keys. */
double
hllRawSum
(
uint8_t
*
registers
,
double
*
PE
,
int
*
ezp
)
{
double
E
=
0
;
int
j
,
ez
=
0
;
unsigned
long
reg
;
for
(
j
=
0
;
j
<
HLL_REGISTERS
;
j
++
)
{
reg
=
registers
[
j
];
if
(
reg
==
0
)
{
ez
++
;
E
+=
1
;
/* 2^(-reg[j]) is 1 when m is 0. */
}
else
{
E
+=
PE
[
reg
];
/* Precomputed 2^(-reg[j]). */
}
}
*
ezp
=
ez
;
return
E
;
}
/* Return the approximated cardinality of the set based on the armonic
* mean of the registers values. 'hdr' points to the start of the SDS
* representing the String object holding the HLL representation.
*
* If the sparse representation of the HLL object is not valid, the integer
* pointed by 'invalid' is set to non-zero, otherwise it is left untouched. */
* pointed by 'invalid' is set to non-zero, otherwise it is left untouched.
*
* hllCount() supports a special internal-only encoding of HLL_RAW, that
* is, hdr->registers will point to an uint8_t array of HLL_REGISTERS element.
* This is useful in order to speedup PFCOUNT when called against multiple
* keys (no need to work with 6-bit integers encoding). */
uint64_t
hllCount
(
struct
hllhdr
*
hdr
,
int
*
invalid
)
{
double
m
=
HLL_REGISTERS
;
double
E
,
alpha
=
0
.
7213
/
(
1
+
1
.
07
9
/
m
);
...
...
@@ -947,9 +973,13 @@ uint64_t hllCount(struct hllhdr *hdr, int *invalid) {
/* Compute SUM(2^-register[0..i]). */
if
(
hdr
->
encoding
==
HLL_DENSE
)
{
E
=
hllDenseSum
(
hdr
->
registers
,
PE
,
&
ez
);
}
else
{
}
else
if
(
hdr
->
encoding
==
HLL_SPARSE
)
{
E
=
hllSparseSum
(
hdr
->
registers
,
sdslen
((
sds
)
hdr
)
-
HLL_HDR_SIZE
,
PE
,
&
ez
,
invalid
);
}
else
if
(
hdr
->
encoding
==
HLL_RAW
)
{
E
=
hllRawSum
(
hdr
->
registers
,
PE
,
&
ez
);
}
else
{
redisPanic
(
"Unknown HyperLogLog encoding in hllCount()"
);
}
/* Muliply the inverse of E for alpha_m * m^2 to have the raw estimate. */
...
...
@@ -1151,10 +1181,47 @@ void pfaddCommand(redisClient *c) {
/* PFCOUNT var -> approximated cardinality of set. */
void
pfcountCommand
(
redisClient
*
c
)
{
robj
*
o
=
lookupKeyRead
(
c
->
db
,
c
->
argv
[
1
])
;
robj
*
o
;
struct
hllhdr
*
hdr
;
uint64_t
card
;
/* Case 1: multi-key keys, cardinality of the union.
*
* When multiple keys are specified, PFCOUNT actually computes
* the cardinality of the merge of the N HLLs specified. */
if
(
c
->
argc
>
2
)
{
uint8_t
max
[
HLL_HDR_SIZE
+
HLL_REGISTERS
],
*
registers
;
int
j
;
/* Compute an HLL with M[i] = MAX(M[i]_j). */
memset
(
max
,
0
,
sizeof
(
max
));
hdr
=
(
struct
hllhdr
*
)
max
;
hdr
->
encoding
=
HLL_RAW
;
/* Special internal-only encoding. */
registers
=
max
+
HLL_HDR_SIZE
;
for
(
j
=
1
;
j
<
c
->
argc
;
j
++
)
{
/* Check type and size. */
robj
*
o
=
lookupKeyRead
(
c
->
db
,
c
->
argv
[
j
]);
if
(
o
==
NULL
)
continue
;
/* Assume empty HLL for non existing var. */
if
(
isHLLObjectOrReply
(
c
,
o
)
!=
REDIS_OK
)
return
;
/* Merge with this HLL with our 'max' HHL by setting max[i]
* to MAX(max[i],hll[i]). */
if
(
hllMerge
(
registers
,
o
)
==
REDIS_ERR
)
{
addReplySds
(
c
,
sdsnew
(
invalid_hll_err
));
return
;
}
}
/* Compute cardinality of the resulting set. */
addReplyLongLong
(
c
,
hllCount
(
hdr
,
NULL
));
return
;
}
/* Case 2: cardinality of the single HLL.
*
* The user specified a single key. Either return the cached value
* or compute one and update the cache. */
o
=
lookupKeyRead
(
c
->
db
,
c
->
argv
[
1
]);
if
(
o
==
NULL
)
{
/* No key? Cardinality is zero since no element was added, otherwise
* we would have a key as HLLADD creates it as a side effect. */
...
...
src/redis.c
浏览文件 @
f0eca148
...
...
@@ -265,7 +265,7 @@ struct redisCommand redisCommandTable[] = {
{
"bitpos"
,
bitposCommand
,
-
3
,
"r"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfselftest"
,
pfselftestCommand
,
1
,
"r"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"pfadd"
,
pfaddCommand
,
-
2
,
"wm"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfcount"
,
pfcountCommand
,
2
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfcount"
,
pfcountCommand
,
-
2
,
"w"
,
0
,
NULL
,
1
,
1
,
1
,
0
,
0
},
{
"pfmerge"
,
pfmergeCommand
,
-
2
,
"wm"
,
0
,
NULL
,
1
,
-
1
,
1
,
0
,
0
},
{
"pfdebug"
,
pfdebugCommand
,
-
3
,
"w"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录