Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xindoo
redis
提交
67def261
R
redis
项目概览
xindoo
/
redis
通知
2
Star
2
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,发现更多精彩内容 >>
提交
67def261
编写于
12月 30, 2016
作者:
O
oranagra
提交者:
antirez
1月 12, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
active memory defragmentation
上级
b4f3c5a4
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
755 addition
and
8 deletion
+755
-8
deps/jemalloc/src/jemalloc.c
deps/jemalloc/src/jemalloc.c
+32
-0
redis.conf
redis.conf
+20
-0
src/Makefile
src/Makefile
+1
-1
src/config.c
src/config.c
+58
-0
src/db.c
src/db.c
+1
-1
src/debug.c
src/debug.c
+12
-3
src/defrag.c
src/defrag.c
+527
-0
src/dict.c
src/dict.c
+33
-0
src/dict.h
src/dict.h
+4
-1
src/server.c
src/server.c
+27
-2
src/server.h
src/server.h
+18
-0
src/zmalloc.c
src/zmalloc.c
+20
-0
src/zmalloc.h
src/zmalloc.h
+2
-0
未找到文件。
deps/jemalloc/src/jemalloc.c
浏览文件 @
67def261
...
...
@@ -2591,3 +2591,35 @@ jemalloc_postfork_child(void)
}
/******************************************************************************/
/* Helps the application decide if a pointer is worth re-allocating in order to reduce fragmentation.
* returns 0 if the allocation is in the currently active run,
* or when it is not causing any frag issue (large or huge bin)
* returns the bin utilization and run utilization both in fixed point 16:16.
* If the application decides to re-allocate it should use MALLOCX_TCACHE_NONE when doing so. */
JEMALLOC_EXPORT
int
JEMALLOC_NOTHROW
je_get_defrag_hint
(
void
*
ptr
,
int
*
bin_util
,
int
*
run_util
)
{
int
defrag
=
0
;
arena_chunk_t
*
chunk
=
(
arena_chunk_t
*
)
CHUNK_ADDR2BASE
(
ptr
);
if
(
likely
(
chunk
!=
ptr
))
{
/* indication that this is not a HUGE alloc */
size_t
pageind
=
((
uintptr_t
)
ptr
-
(
uintptr_t
)
chunk
)
>>
LG_PAGE
;
size_t
mapbits
=
arena_mapbits_get
(
chunk
,
pageind
);
if
(
likely
((
mapbits
&
CHUNK_MAP_LARGE
)
==
0
))
{
/* indication that this is not a LARGE alloc */
arena_t
*
arena
=
extent_node_arena_get
(
&
chunk
->
node
);
size_t
rpages_ind
=
pageind
-
arena_mapbits_small_runind_get
(
chunk
,
pageind
);
arena_run_t
*
run
=
&
arena_miscelm_get
(
chunk
,
rpages_ind
)
->
run
;
arena_bin_t
*
bin
=
&
arena
->
bins
[
run
->
binind
];
malloc_mutex_lock
(
&
bin
->
lock
);
/* runs that are in the same chunk in as the current chunk, are likely to be the next currun */
if
(
chunk
!=
(
arena_chunk_t
*
)
CHUNK_ADDR2BASE
(
bin
->
runcur
))
{
arena_bin_info_t
*
bin_info
=
&
arena_bin_info
[
run
->
binind
];
size_t
availregs
=
bin_info
->
nregs
*
bin
->
stats
.
curruns
;
*
bin_util
=
(
bin
->
stats
.
curregs
<<
16
)
/
availregs
;
*
run_util
=
((
bin_info
->
nregs
-
run
->
nfree
)
<<
16
)
/
bin_info
->
nregs
;
defrag
=
1
;
}
malloc_mutex_unlock
(
&
bin
->
lock
);
}
}
return
defrag
;
}
redis.conf
浏览文件 @
67def261
...
...
@@ -1228,3 +1228,23 @@ aof-rewrite-incremental-fsync yes
#
# lfu-log-factor 10
# lfu-decay-time 1
########################### ACTIVE DEFRAGMENTATION #######################
# enabled active defragmentation
# activedefrag yes
# minimum amount of fragmentation waste to start active defrag
# active-defrag-ignore-bytes 100mb
# minimum percentage of fragmentation to start active defrag
# active-defrag-threshold-lower 10
# maximum percentage of fragmentation at which we use maximum effort
# active-defrag-threshold-upper 100
# minimal effort for defrag in CPU percentage
# active-defrag-cycle-min 25
# maximal effort for defrag in CPU percentage
# active-defrag-cycle-max 75
src/Makefile
浏览文件 @
67def261
...
...
@@ -128,7 +128,7 @@ endif
REDIS_SERVER_NAME
=
redis-server
REDIS_SENTINEL_NAME
=
redis-sentinel
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o
REDIS_SERVER_OBJ
=
adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o
defrag.o
REDIS_CLI_NAME
=
redis-cli
REDIS_CLI_OBJ
=
anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
REDIS_BENCHMARK_NAME
=
redis-benchmark
...
...
src/config.c
浏览文件 @
67def261
...
...
@@ -423,6 +423,10 @@ void loadServerConfigFromString(char *config) {
if
((
server
.
repl_slave_lazy_flush
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"activedefrag"
)
&&
argc
==
2
)
{
if
((
server
.
active_defrag_enabled
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"daemonize"
)
&&
argc
==
2
)
{
if
((
server
.
daemonize
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
...
...
@@ -499,6 +503,36 @@ void loadServerConfigFromString(char *config) {
}
zfree
(
server
.
rdb_filename
);
server
.
rdb_filename
=
zstrdup
(
argv
[
1
]);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-defrag-threshold-lower"
)
&&
argc
==
2
)
{
server
.
active_defrag_threshold_lower
=
atoi
(
argv
[
1
]);
if
(
server
.
active_defrag_threshold_lower
<
0
)
{
err
=
"active-defrag-threshold-lower must be 0 or greater"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-defrag-threshold-upper"
)
&&
argc
==
2
)
{
server
.
active_defrag_threshold_upper
=
atoi
(
argv
[
1
]);
if
(
server
.
active_defrag_threshold_upper
<
0
)
{
err
=
"active-defrag-threshold-upper must be 0 or greater"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-defrag-ignore-bytes"
)
&&
argc
==
2
)
{
server
.
active_defrag_ignore_bytes
=
memtoll
(
argv
[
1
],
NULL
);
if
(
server
.
active_defrag_ignore_bytes
<=
0
)
{
err
=
"active-defrag-ignore-bytes must above 0"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-defrag-cycle-min"
)
&&
argc
==
2
)
{
server
.
active_defrag_cycle_min
=
atoi
(
argv
[
1
]);
if
(
server
.
active_defrag_cycle_min
<
1
||
server
.
active_defrag_cycle_min
>
99
)
{
err
=
"active-defrag-cycle-min must be between 1 and 99"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"active-defrag-cycle-max"
)
&&
argc
==
2
)
{
server
.
active_defrag_cycle_max
=
atoi
(
argv
[
1
]);
if
(
server
.
active_defrag_cycle_max
<
1
||
server
.
active_defrag_cycle_max
>
99
)
{
err
=
"active-defrag-cycle-max must be between 1 and 99"
;
goto
loaderr
;
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-entries"
)
&&
argc
==
2
)
{
server
.
hash_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-value"
)
&&
argc
==
2
)
{
...
...
@@ -971,6 +1005,8 @@ void configSetCommand(client *c) {
"slave-read-only"
,
server
.
repl_slave_ro
)
{
}
config_set_bool_field
(
"activerehashing"
,
server
.
activerehashing
)
{
}
config_set_bool_field
(
"activedefrag"
,
server
.
active_defrag_enabled
)
{
}
config_set_bool_field
(
"protected-mode"
,
server
.
protected_mode
)
{
}
config_set_bool_field
(
...
...
@@ -998,6 +1034,16 @@ void configSetCommand(client *c) {
"lfu-decay-time"
,
server
.
lfu_decay_time
,
0
,
LLONG_MAX
)
{
}
config_set_numerical_field
(
"timeout"
,
server
.
maxidletime
,
0
,
LONG_MAX
)
{
}
config_set_numerical_field
(
"active-defrag-threshold-lower"
,
server
.
active_defrag_threshold_lower
,
0
,
1000
)
{
}
config_set_numerical_field
(
"active-defrag-threshold-upper"
,
server
.
active_defrag_threshold_upper
,
0
,
1000
)
{
}
config_set_memory_field
(
"active-defrag-ignore-bytes"
,
server
.
active_defrag_ignore_bytes
)
{
}
config_set_numerical_field
(
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
,
1
,
99
)
{
}
config_set_numerical_field
(
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
1
,
99
)
{
}
config_set_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
,
0
,
LLONG_MAX
){
}
config_set_numerical_field
(
...
...
@@ -1166,6 +1212,11 @@ void configGetCommand(client *c) {
config_get_numerical_field
(
"maxmemory"
,
server
.
maxmemory
);
config_get_numerical_field
(
"maxmemory-samples"
,
server
.
maxmemory_samples
);
config_get_numerical_field
(
"timeout"
,
server
.
maxidletime
);
config_get_numerical_field
(
"active-defrag-threshold-lower"
,
server
.
active_defrag_threshold_lower
);
config_get_numerical_field
(
"active-defrag-threshold-upper"
,
server
.
active_defrag_threshold_upper
);
config_get_numerical_field
(
"active-defrag-ignore-bytes"
,
server
.
active_defrag_ignore_bytes
);
config_get_numerical_field
(
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
);
config_get_numerical_field
(
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
);
config_get_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
);
config_get_numerical_field
(
"auto-aof-rewrite-min-size"
,
...
...
@@ -1230,6 +1281,7 @@ void configGetCommand(client *c) {
config_get_bool_field
(
"rdbcompression"
,
server
.
rdb_compression
);
config_get_bool_field
(
"rdbchecksum"
,
server
.
rdb_checksum
);
config_get_bool_field
(
"activerehashing"
,
server
.
activerehashing
);
config_get_bool_field
(
"activedefrag"
,
server
.
active_defrag_enabled
);
config_get_bool_field
(
"protected-mode"
,
server
.
protected_mode
);
config_get_bool_field
(
"repl-disable-tcp-nodelay"
,
server
.
repl_disable_tcp_nodelay
);
...
...
@@ -1930,6 +1982,11 @@ int rewriteConfig(char *path) {
rewriteConfigBytesOption
(
state
,
"maxmemory"
,
server
.
maxmemory
,
CONFIG_DEFAULT_MAXMEMORY
);
rewriteConfigEnumOption
(
state
,
"maxmemory-policy"
,
server
.
maxmemory_policy
,
maxmemory_policy_enum
,
CONFIG_DEFAULT_MAXMEMORY_POLICY
);
rewriteConfigNumericalOption
(
state
,
"maxmemory-samples"
,
server
.
maxmemory_samples
,
CONFIG_DEFAULT_MAXMEMORY_SAMPLES
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-threshold-lower"
,
server
.
active_defrag_threshold_lower
,
CONFIG_DEFAULT_DEFRAG_THRESHOLD_LOWER
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-threshold-upper"
,
server
.
active_defrag_threshold_upper
,
CONFIG_DEFAULT_DEFRAG_THRESHOLD_UPPER
);
rewriteConfigBytesOption
(
state
,
"active-defrag-ignore-bytes"
,
server
.
active_defrag_ignore_bytes
,
CONFIG_DEFAULT_DEFRAG_IGNORE_BYTES
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-min"
,
server
.
active_defrag_cycle_min
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MIN
);
rewriteConfigNumericalOption
(
state
,
"active-defrag-cycle-max"
,
server
.
active_defrag_cycle_max
,
CONFIG_DEFAULT_DEFRAG_CYCLE_MAX
);
rewriteConfigYesNoOption
(
state
,
"appendonly"
,
server
.
aof_state
!=
AOF_OFF
,
0
);
rewriteConfigStringOption
(
state
,
"appendfilename"
,
server
.
aof_filename
,
CONFIG_DEFAULT_AOF_FILENAME
);
rewriteConfigEnumOption
(
state
,
"appendfsync"
,
server
.
aof_fsync
,
aof_fsync_enum
,
CONFIG_DEFAULT_AOF_FSYNC
);
...
...
@@ -1956,6 +2013,7 @@ int rewriteConfig(char *path) {
rewriteConfigNumericalOption
(
state
,
"zset-max-ziplist-value"
,
server
.
zset_max_ziplist_value
,
OBJ_ZSET_MAX_ZIPLIST_VALUE
);
rewriteConfigNumericalOption
(
state
,
"hll-sparse-max-bytes"
,
server
.
hll_sparse_max_bytes
,
CONFIG_DEFAULT_HLL_SPARSE_MAX_BYTES
);
rewriteConfigYesNoOption
(
state
,
"activerehashing"
,
server
.
activerehashing
,
CONFIG_DEFAULT_ACTIVE_REHASHING
);
rewriteConfigYesNoOption
(
state
,
"activedefrag"
,
server
.
active_defrag_enabled
,
CONFIG_DEFAULT_ACTIVE_DEFRAG
);
rewriteConfigYesNoOption
(
state
,
"protected-mode"
,
server
.
protected_mode
,
CONFIG_DEFAULT_PROTECTED_MODE
);
rewriteConfigClientoutputbufferlimitOption
(
state
);
rewriteConfigNumericalOption
(
state
,
"hz"
,
server
.
hz
,
CONFIG_DEFAULT_HZ
);
...
...
src/db.c
浏览文件 @
67def261
...
...
@@ -665,7 +665,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
privdata
[
0
]
=
keys
;
privdata
[
1
]
=
o
;
do
{
cursor
=
dictScan
(
ht
,
cursor
,
scanCallback
,
privdata
);
cursor
=
dictScan
(
ht
,
cursor
,
scanCallback
,
NULL
,
privdata
);
}
while
(
cursor
&&
maxiterations
--
&&
listLength
(
keys
)
<
(
unsigned
long
)
count
);
...
...
src/debug.c
浏览文件 @
67def261
...
...
@@ -282,7 +282,7 @@ void debugCommand(client *c) {
blen
++
;
addReplyStatus
(
c
,
"ziplist <key> -- Show low level info about the ziplist encoding."
);
blen
++
;
addReplyStatus
(
c
,
"populate <count> [prefix] -- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix."
);
"populate <count> [prefix]
[size]
-- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix."
);
blen
++
;
addReplyStatus
(
c
,
"digest -- Outputs an hex signature representing the current DB content."
);
blen
++
;
addReplyStatus
(
c
,
...
...
@@ -433,7 +433,7 @@ void debugCommand(client *c) {
addReplyStatus
(
c
,
"Ziplist structure printed on stdout"
);
}
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"populate"
)
&&
(
c
->
argc
==
3
||
c
->
argc
==
4
)
)
{
c
->
argc
>=
3
&&
c
->
argc
<=
5
)
{
long
keys
,
j
;
robj
*
key
,
*
val
;
char
buf
[
128
];
...
...
@@ -442,15 +442,24 @@ void debugCommand(client *c) {
return
;
dictExpand
(
c
->
db
->
dict
,
keys
);
for
(
j
=
0
;
j
<
keys
;
j
++
)
{
long
valsize
=
0
;
snprintf
(
buf
,
sizeof
(
buf
),
"%s:%lu"
,
(
c
->
argc
==
3
)
?
"key"
:
(
char
*
)
c
->
argv
[
3
]
->
ptr
,
j
);
key
=
createStringObject
(
buf
,
strlen
(
buf
));
if
(
c
->
argc
==
5
)
if
(
getLongFromObjectOrReply
(
c
,
c
->
argv
[
4
],
&
valsize
,
NULL
)
!=
C_OK
)
return
;
if
(
lookupKeyWrite
(
c
->
db
,
key
)
!=
NULL
)
{
decrRefCount
(
key
);
continue
;
}
snprintf
(
buf
,
sizeof
(
buf
),
"value:%lu"
,
j
);
val
=
createStringObject
(
buf
,
strlen
(
buf
));
if
(
valsize
==
0
)
val
=
createStringObject
(
buf
,
strlen
(
buf
));
else
{
val
=
createStringObject
(
NULL
,
valsize
);
memset
(
val
->
ptr
,
0
,
valsize
);
}
dbAdd
(
c
->
db
,
key
,
val
);
signalModifiedKey
(
c
->
db
,
key
);
decrRefCount
(
key
);
...
...
src/defrag.c
0 → 100644
浏览文件 @
67def261
此差异已折叠。
点击以展开。
src/dict.c
浏览文件 @
67def261
...
...
@@ -885,6 +885,7 @@ static unsigned long rev(unsigned long v) {
unsigned
long
dictScan
(
dict
*
d
,
unsigned
long
v
,
dictScanFunction
*
fn
,
dictScanBucketFunction
*
bucketfn
,
void
*
privdata
)
{
dictht
*
t0
,
*
t1
;
...
...
@@ -898,6 +899,7 @@ unsigned long dictScan(dict *d,
m0
=
t0
->
sizemask
;
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t0
->
table
[
v
&
m0
]);
de
=
t0
->
table
[
v
&
m0
];
while
(
de
)
{
next
=
de
->
next
;
...
...
@@ -919,6 +921,7 @@ unsigned long dictScan(dict *d,
m1
=
t1
->
sizemask
;
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t0
->
table
[
v
&
m0
]);
de
=
t0
->
table
[
v
&
m0
];
while
(
de
)
{
next
=
de
->
next
;
...
...
@@ -930,6 +933,7 @@ unsigned long dictScan(dict *d,
* of the index pointed to by the cursor in the smaller table */
do
{
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t1
->
table
[
v
&
m1
]);
de
=
t1
->
table
[
v
&
m1
];
while
(
de
)
{
next
=
de
->
next
;
...
...
@@ -1040,6 +1044,35 @@ void dictDisableResize(void) {
dict_can_resize
=
0
;
}
unsigned
int
dictGetHash
(
dict
*
d
,
const
void
*
key
)
{
return
dictHashKey
(
d
,
key
);
}
/* Replace an old key pointer in the dictionary with a new pointer.
* oldkey is a dead pointer and should not be accessed.
* the hash value should be provided using dictGetHash.
* no string / key comparison is performed.
* return value is the dictEntry if found, or NULL if not found. */
dictEntry
*
dictReplaceKeyPtr
(
dict
*
d
,
const
void
*
oldptr
,
void
*
newptr
,
unsigned
int
hash
)
{
dictEntry
*
he
;
unsigned
int
idx
,
table
;
if
(
d
->
ht
[
0
].
used
+
d
->
ht
[
1
].
used
==
0
)
return
NULL
;
/* dict is empty */
for
(
table
=
0
;
table
<=
1
;
table
++
)
{
idx
=
hash
&
d
->
ht
[
table
].
sizemask
;
he
=
d
->
ht
[
table
].
table
[
idx
];
while
(
he
)
{
if
(
oldptr
==
he
->
key
)
{
he
->
key
=
newptr
;
return
he
;
}
he
=
he
->
next
;
}
if
(
!
dictIsRehashing
(
d
))
return
NULL
;
}
return
NULL
;
}
/* ------------------------------- Debugging ---------------------------------*/
#define DICT_STATS_VECTLEN 50
...
...
src/dict.h
浏览文件 @
67def261
...
...
@@ -95,6 +95,7 @@ typedef struct dictIterator {
}
dictIterator
;
typedef
void
(
dictScanFunction
)(
void
*
privdata
,
const
dictEntry
*
de
);
typedef
void
(
dictScanBucketFunction
)(
void
*
privdata
,
dictEntry
**
bucketref
);
/* This is the initial size of every hash table */
#define DICT_HT_INITIAL_SIZE 4
...
...
@@ -176,7 +177,9 @@ int dictRehash(dict *d, int n);
int
dictRehashMilliseconds
(
dict
*
d
,
int
ms
);
void
dictSetHashFunctionSeed
(
unsigned
int
initval
);
unsigned
int
dictGetHashFunctionSeed
(
void
);
unsigned
long
dictScan
(
dict
*
d
,
unsigned
long
v
,
dictScanFunction
*
fn
,
void
*
privdata
);
unsigned
long
dictScan
(
dict
*
d
,
unsigned
long
v
,
dictScanFunction
*
fn
,
dictScanBucketFunction
*
bucketfn
,
void
*
privdata
);
unsigned
int
dictGetHash
(
dict
*
d
,
const
void
*
key
);
dictEntry
*
dictReplaceKeyPtr
(
dict
*
d
,
const
void
*
oldptr
,
void
*
newptr
,
unsigned
int
hash
);
/* Hash table types */
extern
dictType
dictTypeHeapStringCopyKey
;
...
...
src/server.c
浏览文件 @
67def261
...
...
@@ -876,6 +876,10 @@ void databasesCron(void) {
expireSlaveKeys
();
}
/* Defrag keys gradually. */
if
(
server
.
active_defrag_enabled
)
activeDefragCycle
();
/* Perform hash tables rehashing if needed, but only if there are no
* other processes saving the DB on disk. Otherwise rehashing is bad
* as will cause a lot of copy-on-write of memory pages. */
...
...
@@ -1332,6 +1336,12 @@ void initServerConfig(void) {
server
.
maxidletime
=
CONFIG_DEFAULT_CLIENT_TIMEOUT
;
server
.
tcpkeepalive
=
CONFIG_DEFAULT_TCP_KEEPALIVE
;
server
.
active_expire_enabled
=
1
;
server
.
active_defrag_enabled
=
CONFIG_DEFAULT_ACTIVE_DEFRAG
;
server
.
active_defrag_ignore_bytes
=
CONFIG_DEFAULT_DEFRAG_IGNORE_BYTES
;
server
.
active_defrag_threshold_lower
=
CONFIG_DEFAULT_DEFRAG_THRESHOLD_LOWER
;
server
.
active_defrag_threshold_upper
=
CONFIG_DEFAULT_DEFRAG_THRESHOLD_UPPER
;
server
.
active_defrag_cycle_min
=
CONFIG_DEFAULT_DEFRAG_CYCLE_MIN
;
server
.
active_defrag_cycle_max
=
CONFIG_DEFAULT_DEFRAG_CYCLE_MAX
;
server
.
client_max_querybuf_len
=
PROTO_MAX_QUERYBUF_LEN
;
server
.
saveparams
=
NULL
;
server
.
loading
=
0
;
...
...
@@ -1368,6 +1378,7 @@ void initServerConfig(void) {
server
.
rdb_checksum
=
CONFIG_DEFAULT_RDB_CHECKSUM
;
server
.
stop_writes_on_bgsave_err
=
CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR
;
server
.
activerehashing
=
CONFIG_DEFAULT_ACTIVE_REHASHING
;
server
.
active_defrag_running
=
0
;
server
.
notify_keyspace_events
=
0
;
server
.
maxclients
=
CONFIG_DEFAULT_MAX_CLIENTS
;
server
.
bpop_blocked_clients
=
0
;
...
...
@@ -1718,6 +1729,10 @@ void resetServerStats(void) {
server
.
stat_evictedkeys
=
0
;
server
.
stat_keyspace_misses
=
0
;
server
.
stat_keyspace_hits
=
0
;
server
.
stat_active_defrag_hits
=
0
;
server
.
stat_active_defrag_misses
=
0
;
server
.
stat_active_defrag_key_hits
=
0
;
server
.
stat_active_defrag_key_misses
=
0
;
server
.
stat_fork_time
=
0
;
server
.
stat_fork_rate
=
0
;
server
.
stat_rejected_conn
=
0
;
...
...
@@ -2873,6 +2888,7 @@ sds genRedisInfoString(char *section) {
"maxmemory_policy:%s
\r\n
"
"mem_fragmentation_ratio:%.2f
\r\n
"
"mem_allocator:%s
\r\n
"
"active_defrag_running:%d
\r\n
"
"lazyfree_pending_objects:%zu
\r\n
"
,
zmalloc_used
,
hmem
,
...
...
@@ -2894,6 +2910,7 @@ sds genRedisInfoString(char *section) {
evict_policy
,
mh
->
fragmentation
,
ZMALLOC_LIB
,
server
.
active_defrag_running
,
lazyfreeGetPendingObjectsCount
()
);
freeMemoryOverheadData
(
mh
);
...
...
@@ -3013,7 +3030,11 @@ sds genRedisInfoString(char *section) {
"pubsub_patterns:%lu
\r\n
"
"latest_fork_usec:%lld
\r\n
"
"migrate_cached_sockets:%ld
\r\n
"
"slave_expires_tracked_keys:%zu
\r\n
"
,
"slave_expires_tracked_keys:%zu
\r\n
"
"active_defrag_hits:%lld
\r\n
"
"active_defrag_misses:%lld
\r\n
"
"active_defrag_key_hits:%lld
\r\n
"
"active_defrag_key_misses:%lld
\r\n
"
,
server
.
stat_numconnections
,
server
.
stat_numcommands
,
getInstantaneousMetric
(
STATS_METRIC_COMMAND
),
...
...
@@ -3033,7 +3054,11 @@ sds genRedisInfoString(char *section) {
listLength
(
server
.
pubsub_patterns
),
server
.
stat_fork_time
,
dictSize
(
server
.
migrate_cached_sockets
),
getSlaveKeyWithExpireCount
());
getSlaveKeyWithExpireCount
(),
server
.
stat_active_defrag_hits
,
server
.
stat_active_defrag_misses
,
server
.
stat_active_defrag_key_hits
,
server
.
stat_active_defrag_key_misses
);
}
/* Replication */
...
...
src/server.h
浏览文件 @
67def261
...
...
@@ -152,6 +152,12 @@ typedef long long mstime_t; /* millisecond time type. */
#define CONFIG_DEFAULT_LAZYFREE_LAZY_EXPIRE 0
#define CONFIG_DEFAULT_LAZYFREE_LAZY_SERVER_DEL 0
#define CONFIG_DEFAULT_ALWAYS_SHOW_LOGO 0
#define CONFIG_DEFAULT_ACTIVE_DEFRAG 1
#define CONFIG_DEFAULT_DEFRAG_THRESHOLD_LOWER 10
/* don't defrag when fragmentation is below 10% */
#define CONFIG_DEFAULT_DEFRAG_THRESHOLD_UPPER 100
/* maximum defrag force at 100% fragmentation */
#define CONFIG_DEFAULT_DEFRAG_IGNORE_BYTES (100<<20)
/* don't defrag if frag overhead is below 100mb */
#define CONFIG_DEFAULT_DEFRAG_CYCLE_MIN 25
/* 25% CPU min (at lower threshold) */
#define CONFIG_DEFAULT_DEFRAG_CYCLE_MAX 75
/* 75% CPU max (at upper threshold) */
#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20
/* Loopkups per loop. */
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000
/* Microseconds */
...
...
@@ -857,6 +863,7 @@ struct redisServer {
unsigned
lruclock
:
LRU_BITS
;
/* Clock for LRU eviction */
int
shutdown_asap
;
/* SHUTDOWN needed ASAP */
int
activerehashing
;
/* Incremental rehash in serverCron() */
int
active_defrag_running
;
/* Active defragmentation running (holds current scan aggressiveness) */
char
*
requirepass
;
/* Pass for AUTH command, or NULL */
char
*
pidfile
;
/* PID file path */
int
arch_bits
;
/* 32 or 64 depending on sizeof(long) */
...
...
@@ -908,6 +915,10 @@ struct redisServer {
long
long
stat_evictedkeys
;
/* Number of evicted keys (maxmemory) */
long
long
stat_keyspace_hits
;
/* Number of successful lookups of keys */
long
long
stat_keyspace_misses
;
/* Number of failed lookups of keys */
long
long
stat_active_defrag_hits
;
/* number of allocations moved */
long
long
stat_active_defrag_misses
;
/* number of allocations scanned but not moved */
long
long
stat_active_defrag_key_hits
;
/* number of keys with moved allocations */
long
long
stat_active_defrag_key_misses
;
/* number of keys scanned and not moved */
size_t
stat_peak_memory
;
/* Max used memory record */
long
long
stat_fork_time
;
/* Time needed to perform latest fork() */
double
stat_fork_rate
;
/* Fork rate in GB/sec. */
...
...
@@ -937,6 +948,12 @@ struct redisServer {
int
maxidletime
;
/* Client timeout in seconds */
int
tcpkeepalive
;
/* Set SO_KEEPALIVE if non-zero. */
int
active_expire_enabled
;
/* Can be disabled for testing purposes. */
int
active_defrag_enabled
;
size_t
active_defrag_ignore_bytes
;
/* minimum amount of fragmentation waste to start active defrag */
int
active_defrag_threshold_lower
;
/* minimum percentage of fragmentation to start active defrag */
int
active_defrag_threshold_upper
;
/* maximum percentage of fragmentation at which we use maximum effort */
int
active_defrag_cycle_min
;
/* minimal effort for defrag in CPU percentage */
int
active_defrag_cycle_max
;
/* maximal effort for defrag in CPU percentage */
size_t
client_max_querybuf_len
;
/* Limit for client query buffer length */
int
dbnum
;
/* Total number of configured DBs */
int
supervised
;
/* 1 if supervised, 0 otherwise. */
...
...
@@ -1576,6 +1593,7 @@ void adjustOpenFilesLimit(void);
void
closeListeningSockets
(
int
unlink_unix_socket
);
void
updateCachedTime
(
void
);
void
resetServerStats
(
void
);
void
activeDefragCycle
(
void
);
unsigned
int
getLRUClock
(
void
);
const
char
*
evictPolicyToString
(
void
);
struct
redisMemOverhead
*
getMemoryOverheadData
(
void
);
...
...
src/zmalloc.c
浏览文件 @
67def261
...
...
@@ -66,6 +66,8 @@ void zlibc_free(void *ptr) {
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#define mallocx(size,flags) je_mallocx(size,flags)
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
#endif
#define update_zmalloc_stat_alloc(__n) do { \
...
...
@@ -115,6 +117,24 @@ void *zmalloc(size_t size) {
#endif
}
/* Allocation and free functions that bypass the thread cache
* and go straight to the allocator arena bins.
* Currently implemented only for jemalloc */
#if defined(USE_JEMALLOC) && defined(MALLOCX_TCACHE_NONE)
void
*
zmalloc_no_tcache
(
size_t
size
)
{
void
*
ptr
=
mallocx
(
size
+
PREFIX_SIZE
,
MALLOCX_TCACHE_NONE
);
if
(
!
ptr
)
zmalloc_oom_handler
(
size
);
update_zmalloc_stat_alloc
(
zmalloc_size
(
ptr
));
return
ptr
;
}
void
zfree_no_tcache
(
void
*
ptr
)
{
if
(
ptr
==
NULL
)
return
;
update_zmalloc_stat_free
(
zmalloc_size
(
ptr
));
dallocx
(
ptr
,
MALLOCX_TCACHE_NONE
);
}
#endif
void
*
zcalloc
(
size_t
size
)
{
void
*
ptr
=
calloc
(
1
,
size
+
PREFIX_SIZE
);
...
...
src/zmalloc.h
浏览文件 @
67def261
...
...
@@ -69,6 +69,8 @@ void *zmalloc(size_t size);
void
*
zcalloc
(
size_t
size
);
void
*
zrealloc
(
void
*
ptr
,
size_t
size
);
void
zfree
(
void
*
ptr
);
void
zfree_no_tcache
(
void
*
ptr
);
void
*
zmalloc_no_tcache
(
size_t
size
);
char
*
zstrdup
(
const
char
*
s
);
size_t
zmalloc_used_memory
(
void
);
void
zmalloc_enable_thread_safeness
(
void
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录