Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
7aa9e6d2
Commit
7aa9e6d2
authored
Dec 30, 2016
by
oranagra
Browse files
active memory defragmentation
parent
6712bce9
Changes
13
Expand all
Show whitespace changes
Inline
Side-by-side
deps/jemalloc/src/jemalloc.c
View file @
7aa9e6d2
...
@@ -2591,3 +2591,35 @@ jemalloc_postfork_child(void)
...
@@ -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
View file @
7aa9e6d2
...
@@ -1228,3 +1228,23 @@ aof-rewrite-incremental-fsync yes
...
@@ -1228,3 +1228,23 @@ aof-rewrite-incremental-fsync yes
#
#
# lfu-log-factor 10
# lfu-log-factor 10
# lfu-decay-time 1
# 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
View file @
7aa9e6d2
...
@@ -128,7 +128,7 @@ endif
...
@@ -128,7 +128,7 @@ endif
REDIS_SERVER_NAME
=
redis-server
REDIS_SERVER_NAME
=
redis-server
REDIS_SENTINEL_NAME
=
redis-sentinel
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_NAME
=
redis-cli
REDIS_CLI_OBJ
=
anet.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o
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
REDIS_BENCHMARK_NAME
=
redis-benchmark
...
...
src/config.c
View file @
7aa9e6d2
...
@@ -423,6 +423,10 @@ void loadServerConfigFromString(char *config) {
...
@@ -423,6 +423,10 @@ void loadServerConfigFromString(char *config) {
if
((
server
.
repl_slave_lazy_flush
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
if
((
server
.
repl_slave_lazy_flush
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
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
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"daemonize"
)
&&
argc
==
2
)
{
if
((
server
.
daemonize
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
if
((
server
.
daemonize
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
...
@@ -499,6 +503,36 @@ void loadServerConfigFromString(char *config) {
...
@@ -499,6 +503,36 @@ void loadServerConfigFromString(char *config) {
}
}
zfree
(
server
.
rdb_filename
);
zfree
(
server
.
rdb_filename
);
server
.
rdb_filename
=
zstrdup
(
argv
[
1
]);
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
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-entries"
)
&&
argc
==
2
)
{
server
.
hash_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
server
.
hash_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-value"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-ziplist-value"
)
&&
argc
==
2
)
{
...
@@ -971,6 +1005,8 @@ void configSetCommand(client *c) {
...
@@ -971,6 +1005,8 @@ void configSetCommand(client *c) {
"slave-read-only"
,
server
.
repl_slave_ro
)
{
"slave-read-only"
,
server
.
repl_slave_ro
)
{
}
config_set_bool_field
(
}
config_set_bool_field
(
"activerehashing"
,
server
.
activerehashing
)
{
"activerehashing"
,
server
.
activerehashing
)
{
}
config_set_bool_field
(
"activedefrag"
,
server
.
active_defrag_enabled
)
{
}
config_set_bool_field
(
}
config_set_bool_field
(
"protected-mode"
,
server
.
protected_mode
)
{
"protected-mode"
,
server
.
protected_mode
)
{
}
config_set_bool_field
(
}
config_set_bool_field
(
...
@@ -998,6 +1034,16 @@ void configSetCommand(client *c) {
...
@@ -998,6 +1034,16 @@ void configSetCommand(client *c) {
"lfu-decay-time"
,
server
.
lfu_decay_time
,
0
,
LLONG_MAX
)
{
"lfu-decay-time"
,
server
.
lfu_decay_time
,
0
,
LLONG_MAX
)
{
}
config_set_numerical_field
(
}
config_set_numerical_field
(
"timeout"
,
server
.
maxidletime
,
0
,
LONG_MAX
)
{
"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
(
}
config_set_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
,
0
,
LLONG_MAX
){
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
,
0
,
LLONG_MAX
){
}
config_set_numerical_field
(
}
config_set_numerical_field
(
...
@@ -1166,6 +1212,11 @@ void configGetCommand(client *c) {
...
@@ -1166,6 +1212,11 @@ void configGetCommand(client *c) {
config_get_numerical_field
(
"maxmemory"
,
server
.
maxmemory
);
config_get_numerical_field
(
"maxmemory"
,
server
.
maxmemory
);
config_get_numerical_field
(
"maxmemory-samples"
,
server
.
maxmemory_samples
);
config_get_numerical_field
(
"maxmemory-samples"
,
server
.
maxmemory_samples
);
config_get_numerical_field
(
"timeout"
,
server
.
maxidletime
);
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"
,
config_get_numerical_field
(
"auto-aof-rewrite-percentage"
,
server
.
aof_rewrite_perc
);
server
.
aof_rewrite_perc
);
config_get_numerical_field
(
"auto-aof-rewrite-min-size"
,
config_get_numerical_field
(
"auto-aof-rewrite-min-size"
,
...
@@ -1230,6 +1281,7 @@ void configGetCommand(client *c) {
...
@@ -1230,6 +1281,7 @@ void configGetCommand(client *c) {
config_get_bool_field
(
"rdbcompression"
,
server
.
rdb_compression
);
config_get_bool_field
(
"rdbcompression"
,
server
.
rdb_compression
);
config_get_bool_field
(
"rdbchecksum"
,
server
.
rdb_checksum
);
config_get_bool_field
(
"rdbchecksum"
,
server
.
rdb_checksum
);
config_get_bool_field
(
"activerehashing"
,
server
.
activerehashing
);
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
(
"protected-mode"
,
server
.
protected_mode
);
config_get_bool_field
(
"repl-disable-tcp-nodelay"
,
config_get_bool_field
(
"repl-disable-tcp-nodelay"
,
server
.
repl_disable_tcp_nodelay
);
server
.
repl_disable_tcp_nodelay
);
...
@@ -1930,6 +1982,11 @@ int rewriteConfig(char *path) {
...
@@ -1930,6 +1982,11 @@ int rewriteConfig(char *path) {
rewriteConfigBytesOption
(
state
,
"maxmemory"
,
server
.
maxmemory
,
CONFIG_DEFAULT_MAXMEMORY
);
rewriteConfigBytesOption
(
state
,
"maxmemory"
,
server
.
maxmemory
,
CONFIG_DEFAULT_MAXMEMORY
);
rewriteConfigEnumOption
(
state
,
"maxmemory-policy"
,
server
.
maxmemory_policy
,
maxmemory_policy_enum
,
CONFIG_DEFAULT_MAXMEMORY_POLICY
);
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
,
"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
);
rewriteConfigYesNoOption
(
state
,
"appendonly"
,
server
.
aof_state
!=
AOF_OFF
,
0
);
rewriteConfigStringOption
(
state
,
"appendfilename"
,
server
.
aof_filename
,
CONFIG_DEFAULT_AOF_FILENAME
);
rewriteConfigStringOption
(
state
,
"appendfilename"
,
server
.
aof_filename
,
CONFIG_DEFAULT_AOF_FILENAME
);
rewriteConfigEnumOption
(
state
,
"appendfsync"
,
server
.
aof_fsync
,
aof_fsync_enum
,
CONFIG_DEFAULT_AOF_FSYNC
);
rewriteConfigEnumOption
(
state
,
"appendfsync"
,
server
.
aof_fsync
,
aof_fsync_enum
,
CONFIG_DEFAULT_AOF_FSYNC
);
...
@@ -1956,6 +2013,7 @@ int rewriteConfig(char *path) {
...
@@ -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
,
"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
);
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
,
"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
);
rewriteConfigYesNoOption
(
state
,
"protected-mode"
,
server
.
protected_mode
,
CONFIG_DEFAULT_PROTECTED_MODE
);
rewriteConfigClientoutputbufferlimitOption
(
state
);
rewriteConfigClientoutputbufferlimitOption
(
state
);
rewriteConfigNumericalOption
(
state
,
"hz"
,
server
.
hz
,
CONFIG_DEFAULT_HZ
);
rewriteConfigNumericalOption
(
state
,
"hz"
,
server
.
hz
,
CONFIG_DEFAULT_HZ
);
...
...
src/db.c
View file @
7aa9e6d2
...
@@ -665,7 +665,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
...
@@ -665,7 +665,7 @@ void scanGenericCommand(client *c, robj *o, unsigned long cursor) {
privdata
[
0
]
=
keys
;
privdata
[
0
]
=
keys
;
privdata
[
1
]
=
o
;
privdata
[
1
]
=
o
;
do
{
do
{
cursor
=
dictScan
(
ht
,
cursor
,
scanCallback
,
privdata
);
cursor
=
dictScan
(
ht
,
cursor
,
scanCallback
,
NULL
,
privdata
);
}
while
(
cursor
&&
}
while
(
cursor
&&
maxiterations
--
&&
maxiterations
--
&&
listLength
(
keys
)
<
(
unsigned
long
)
count
);
listLength
(
keys
)
<
(
unsigned
long
)
count
);
...
...
src/debug.c
View file @
7aa9e6d2
...
@@ -282,7 +282,7 @@ void debugCommand(client *c) {
...
@@ -282,7 +282,7 @@ void debugCommand(client *c) {
blen
++
;
addReplyStatus
(
c
,
blen
++
;
addReplyStatus
(
c
,
"ziplist <key> -- Show low level info about the ziplist encoding."
);
"ziplist <key> -- Show low level info about the ziplist encoding."
);
blen
++
;
addReplyStatus
(
c
,
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
,
blen
++
;
addReplyStatus
(
c
,
"digest -- Outputs an hex signature representing the current DB content."
);
"digest -- Outputs an hex signature representing the current DB content."
);
blen
++
;
addReplyStatus
(
c
,
blen
++
;
addReplyStatus
(
c
,
...
@@ -433,7 +433,7 @@ void debugCommand(client *c) {
...
@@ -433,7 +433,7 @@ void debugCommand(client *c) {
addReplyStatus
(
c
,
"Ziplist structure printed on stdout"
);
addReplyStatus
(
c
,
"Ziplist structure printed on stdout"
);
}
}
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"populate"
)
&&
}
else
if
(
!
strcasecmp
(
c
->
argv
[
1
]
->
ptr
,
"populate"
)
&&
(
c
->
argc
=
=
3
||
c
->
argc
=
=
4
)
)
{
c
->
argc
>
=
3
&&
c
->
argc
<
=
5
)
{
long
keys
,
j
;
long
keys
,
j
;
robj
*
key
,
*
val
;
robj
*
key
,
*
val
;
char
buf
[
128
];
char
buf
[
128
];
...
@@ -442,15 +442,24 @@ void debugCommand(client *c) {
...
@@ -442,15 +442,24 @@ void debugCommand(client *c) {
return
;
return
;
dictExpand
(
c
->
db
->
dict
,
keys
);
dictExpand
(
c
->
db
->
dict
,
keys
);
for
(
j
=
0
;
j
<
keys
;
j
++
)
{
for
(
j
=
0
;
j
<
keys
;
j
++
)
{
long
valsize
=
0
;
snprintf
(
buf
,
sizeof
(
buf
),
"%s:%lu"
,
snprintf
(
buf
,
sizeof
(
buf
),
"%s:%lu"
,
(
c
->
argc
==
3
)
?
"key"
:
(
char
*
)
c
->
argv
[
3
]
->
ptr
,
j
);
(
c
->
argc
==
3
)
?
"key"
:
(
char
*
)
c
->
argv
[
3
]
->
ptr
,
j
);
key
=
createStringObject
(
buf
,
strlen
(
buf
));
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
)
{
if
(
lookupKeyWrite
(
c
->
db
,
key
)
!=
NULL
)
{
decrRefCount
(
key
);
decrRefCount
(
key
);
continue
;
continue
;
}
}
snprintf
(
buf
,
sizeof
(
buf
),
"value:%lu"
,
j
);
snprintf
(
buf
,
sizeof
(
buf
),
"value:%lu"
,
j
);
if
(
valsize
==
0
)
val
=
createStringObject
(
buf
,
strlen
(
buf
));
val
=
createStringObject
(
buf
,
strlen
(
buf
));
else
{
val
=
createStringObject
(
NULL
,
valsize
);
memset
(
val
->
ptr
,
0
,
valsize
);
}
dbAdd
(
c
->
db
,
key
,
val
);
dbAdd
(
c
->
db
,
key
,
val
);
signalModifiedKey
(
c
->
db
,
key
);
signalModifiedKey
(
c
->
db
,
key
);
decrRefCount
(
key
);
decrRefCount
(
key
);
...
...
src/defrag.c
0 → 100644
View file @
7aa9e6d2
This diff is collapsed.
Click to expand it.
src/dict.c
View file @
7aa9e6d2
...
@@ -885,6 +885,7 @@ static unsigned long rev(unsigned long v) {
...
@@ -885,6 +885,7 @@ static unsigned long rev(unsigned long v) {
unsigned
long
dictScan
(
dict
*
d
,
unsigned
long
dictScan
(
dict
*
d
,
unsigned
long
v
,
unsigned
long
v
,
dictScanFunction
*
fn
,
dictScanFunction
*
fn
,
dictScanBucketFunction
*
bucketfn
,
void
*
privdata
)
void
*
privdata
)
{
{
dictht
*
t0
,
*
t1
;
dictht
*
t0
,
*
t1
;
...
@@ -898,6 +899,7 @@ unsigned long dictScan(dict *d,
...
@@ -898,6 +899,7 @@ unsigned long dictScan(dict *d,
m0
=
t0
->
sizemask
;
m0
=
t0
->
sizemask
;
/* Emit entries at cursor */
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t0
->
table
[
v
&
m0
]);
de
=
t0
->
table
[
v
&
m0
];
de
=
t0
->
table
[
v
&
m0
];
while
(
de
)
{
while
(
de
)
{
next
=
de
->
next
;
next
=
de
->
next
;
...
@@ -919,6 +921,7 @@ unsigned long dictScan(dict *d,
...
@@ -919,6 +921,7 @@ unsigned long dictScan(dict *d,
m1
=
t1
->
sizemask
;
m1
=
t1
->
sizemask
;
/* Emit entries at cursor */
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t0
->
table
[
v
&
m0
]);
de
=
t0
->
table
[
v
&
m0
];
de
=
t0
->
table
[
v
&
m0
];
while
(
de
)
{
while
(
de
)
{
next
=
de
->
next
;
next
=
de
->
next
;
...
@@ -930,6 +933,7 @@ unsigned long dictScan(dict *d,
...
@@ -930,6 +933,7 @@ unsigned long dictScan(dict *d,
* of the index pointed to by the cursor in the smaller table */
* of the index pointed to by the cursor in the smaller table */
do
{
do
{
/* Emit entries at cursor */
/* Emit entries at cursor */
if
(
bucketfn
)
bucketfn
(
privdata
,
&
t1
->
table
[
v
&
m1
]);
de
=
t1
->
table
[
v
&
m1
];
de
=
t1
->
table
[
v
&
m1
];
while
(
de
)
{
while
(
de
)
{
next
=
de
->
next
;
next
=
de
->
next
;
...
@@ -1040,6 +1044,35 @@ void dictDisableResize(void) {
...
@@ -1040,6 +1044,35 @@ void dictDisableResize(void) {
dict_can_resize
=
0
;
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 ---------------------------------*/
/* ------------------------------- Debugging ---------------------------------*/
#define DICT_STATS_VECTLEN 50
#define DICT_STATS_VECTLEN 50
...
...
src/dict.h
View file @
7aa9e6d2
...
@@ -95,6 +95,7 @@ typedef struct dictIterator {
...
@@ -95,6 +95,7 @@ typedef struct dictIterator {
}
dictIterator
;
}
dictIterator
;
typedef
void
(
dictScanFunction
)(
void
*
privdata
,
const
dictEntry
*
de
);
typedef
void
(
dictScanFunction
)(
void
*
privdata
,
const
dictEntry
*
de
);
typedef
void
(
dictScanBucketFunction
)(
void
*
privdata
,
dictEntry
**
bucketref
);
/* This is the initial size of every hash table */
/* This is the initial size of every hash table */
#define DICT_HT_INITIAL_SIZE 4
#define DICT_HT_INITIAL_SIZE 4
...
@@ -176,7 +177,9 @@ int dictRehash(dict *d, int n);
...
@@ -176,7 +177,9 @@ int dictRehash(dict *d, int n);
int
dictRehashMilliseconds
(
dict
*
d
,
int
ms
);
int
dictRehashMilliseconds
(
dict
*
d
,
int
ms
);
void
dictSetHashFunctionSeed
(
unsigned
int
initval
);
void
dictSetHashFunctionSeed
(
unsigned
int
initval
);
unsigned
int
dictGetHashFunctionSeed
(
void
);
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 */
/* Hash table types */
extern
dictType
dictTypeHeapStringCopyKey
;
extern
dictType
dictTypeHeapStringCopyKey
;
...
...
src/server.c
View file @
7aa9e6d2
...
@@ -876,6 +876,10 @@ void databasesCron(void) {
...
@@ -876,6 +876,10 @@ void databasesCron(void) {
expireSlaveKeys
();
expireSlaveKeys
();
}
}
/* Defrag keys gradually. */
if
(
server
.
active_defrag_enabled
)
activeDefragCycle
();
/* Perform hash tables rehashing if needed, but only if there are no
/* Perform hash tables rehashing if needed, but only if there are no
* other processes saving the DB on disk. Otherwise rehashing is bad
* other processes saving the DB on disk. Otherwise rehashing is bad
* as will cause a lot of copy-on-write of memory pages. */
* as will cause a lot of copy-on-write of memory pages. */
...
@@ -1332,6 +1336,12 @@ void initServerConfig(void) {
...
@@ -1332,6 +1336,12 @@ void initServerConfig(void) {
server
.
maxidletime
=
CONFIG_DEFAULT_CLIENT_TIMEOUT
;
server
.
maxidletime
=
CONFIG_DEFAULT_CLIENT_TIMEOUT
;
server
.
tcpkeepalive
=
CONFIG_DEFAULT_TCP_KEEPALIVE
;
server
.
tcpkeepalive
=
CONFIG_DEFAULT_TCP_KEEPALIVE
;
server
.
active_expire_enabled
=
1
;
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
.
client_max_querybuf_len
=
PROTO_MAX_QUERYBUF_LEN
;
server
.
saveparams
=
NULL
;
server
.
saveparams
=
NULL
;
server
.
loading
=
0
;
server
.
loading
=
0
;
...
@@ -1368,6 +1378,7 @@ void initServerConfig(void) {
...
@@ -1368,6 +1378,7 @@ void initServerConfig(void) {
server
.
rdb_checksum
=
CONFIG_DEFAULT_RDB_CHECKSUM
;
server
.
rdb_checksum
=
CONFIG_DEFAULT_RDB_CHECKSUM
;
server
.
stop_writes_on_bgsave_err
=
CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR
;
server
.
stop_writes_on_bgsave_err
=
CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR
;
server
.
activerehashing
=
CONFIG_DEFAULT_ACTIVE_REHASHING
;
server
.
activerehashing
=
CONFIG_DEFAULT_ACTIVE_REHASHING
;
server
.
active_defrag_running
=
0
;
server
.
notify_keyspace_events
=
0
;
server
.
notify_keyspace_events
=
0
;
server
.
maxclients
=
CONFIG_DEFAULT_MAX_CLIENTS
;
server
.
maxclients
=
CONFIG_DEFAULT_MAX_CLIENTS
;
server
.
bpop_blocked_clients
=
0
;
server
.
bpop_blocked_clients
=
0
;
...
@@ -1718,6 +1729,10 @@ void resetServerStats(void) {
...
@@ -1718,6 +1729,10 @@ void resetServerStats(void) {
server
.
stat_evictedkeys
=
0
;
server
.
stat_evictedkeys
=
0
;
server
.
stat_keyspace_misses
=
0
;
server
.
stat_keyspace_misses
=
0
;
server
.
stat_keyspace_hits
=
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_time
=
0
;
server
.
stat_fork_rate
=
0
;
server
.
stat_fork_rate
=
0
;
server
.
stat_rejected_conn
=
0
;
server
.
stat_rejected_conn
=
0
;
...
@@ -2873,6 +2888,7 @@ sds genRedisInfoString(char *section) {
...
@@ -2873,6 +2888,7 @@ sds genRedisInfoString(char *section) {
"maxmemory_policy:%s
\r\n
"
"maxmemory_policy:%s
\r\n
"
"mem_fragmentation_ratio:%.2f
\r\n
"
"mem_fragmentation_ratio:%.2f
\r\n
"
"mem_allocator:%s
\r\n
"
"mem_allocator:%s
\r\n
"
"active_defrag_running:%d
\r\n
"
"lazyfree_pending_objects:%zu
\r\n
"
,
"lazyfree_pending_objects:%zu
\r\n
"
,
zmalloc_used
,
zmalloc_used
,
hmem
,
hmem
,
...
@@ -2894,6 +2910,7 @@ sds genRedisInfoString(char *section) {
...
@@ -2894,6 +2910,7 @@ sds genRedisInfoString(char *section) {
evict_policy
,
evict_policy
,
mh
->
fragmentation
,
mh
->
fragmentation
,
ZMALLOC_LIB
,
ZMALLOC_LIB
,
server
.
active_defrag_running
,
lazyfreeGetPendingObjectsCount
()
lazyfreeGetPendingObjectsCount
()
);
);
freeMemoryOverheadData
(
mh
);
freeMemoryOverheadData
(
mh
);
...
@@ -3013,7 +3030,11 @@ sds genRedisInfoString(char *section) {
...
@@ -3013,7 +3030,11 @@ sds genRedisInfoString(char *section) {
"pubsub_patterns:%lu
\r\n
"
"pubsub_patterns:%lu
\r\n
"
"latest_fork_usec:%lld
\r\n
"
"latest_fork_usec:%lld
\r\n
"
"migrate_cached_sockets:%ld
\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_numconnections
,
server
.
stat_numcommands
,
server
.
stat_numcommands
,
getInstantaneousMetric
(
STATS_METRIC_COMMAND
),
getInstantaneousMetric
(
STATS_METRIC_COMMAND
),
...
@@ -3033,7 +3054,11 @@ sds genRedisInfoString(char *section) {
...
@@ -3033,7 +3054,11 @@ sds genRedisInfoString(char *section) {
listLength
(
server
.
pubsub_patterns
),
listLength
(
server
.
pubsub_patterns
),
server
.
stat_fork_time
,
server
.
stat_fork_time
,
dictSize
(
server
.
migrate_cached_sockets
),
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 */
/* Replication */
...
...
src/server.h
View file @
7aa9e6d2
...
@@ -152,6 +152,12 @@ typedef long long mstime_t; /* millisecond time type. */
...
@@ -152,6 +152,12 @@ typedef long long mstime_t; /* millisecond time type. */
#define CONFIG_DEFAULT_LAZYFREE_LAZY_EXPIRE 0
#define CONFIG_DEFAULT_LAZYFREE_LAZY_EXPIRE 0
#define CONFIG_DEFAULT_LAZYFREE_LAZY_SERVER_DEL 0
#define CONFIG_DEFAULT_LAZYFREE_LAZY_SERVER_DEL 0
#define CONFIG_DEFAULT_ALWAYS_SHOW_LOGO 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_LOOKUPS_PER_LOOP 20
/* Loopkups per loop. */
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000
/* Microseconds */
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000
/* Microseconds */
...
@@ -857,6 +863,7 @@ struct redisServer {
...
@@ -857,6 +863,7 @@ struct redisServer {
unsigned
lruclock
:
LRU_BITS
;
/* Clock for LRU eviction */
unsigned
lruclock
:
LRU_BITS
;
/* Clock for LRU eviction */
int
shutdown_asap
;
/* SHUTDOWN needed ASAP */
int
shutdown_asap
;
/* SHUTDOWN needed ASAP */
int
activerehashing
;
/* Incremental rehash in serverCron() */
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
*
requirepass
;
/* Pass for AUTH command, or NULL */
char
*
pidfile
;
/* PID file path */
char
*
pidfile
;
/* PID file path */
int
arch_bits
;
/* 32 or 64 depending on sizeof(long) */
int
arch_bits
;
/* 32 or 64 depending on sizeof(long) */
...
@@ -908,6 +915,10 @@ struct redisServer {
...
@@ -908,6 +915,10 @@ struct redisServer {
long
long
stat_evictedkeys
;
/* Number of evicted keys (maxmemory) */
long
long
stat_evictedkeys
;
/* Number of evicted keys (maxmemory) */
long
long
stat_keyspace_hits
;
/* Number of successful lookups of keys */
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_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 */
size_t
stat_peak_memory
;
/* Max used memory record */
long
long
stat_fork_time
;
/* Time needed to perform latest fork() */
long
long
stat_fork_time
;
/* Time needed to perform latest fork() */
double
stat_fork_rate
;
/* Fork rate in GB/sec. */
double
stat_fork_rate
;
/* Fork rate in GB/sec. */
...
@@ -937,6 +948,12 @@ struct redisServer {
...
@@ -937,6 +948,12 @@ struct redisServer {
int
maxidletime
;
/* Client timeout in seconds */
int
maxidletime
;
/* Client timeout in seconds */
int
tcpkeepalive
;
/* Set SO_KEEPALIVE if non-zero. */
int
tcpkeepalive
;
/* Set SO_KEEPALIVE if non-zero. */
int
active_expire_enabled
;
/* Can be disabled for testing purposes. */
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 */
size_t
client_max_querybuf_len
;
/* Limit for client query buffer length */
int
dbnum
;
/* Total number of configured DBs */
int
dbnum
;
/* Total number of configured DBs */
int
supervised
;
/* 1 if supervised, 0 otherwise. */
int
supervised
;
/* 1 if supervised, 0 otherwise. */
...
@@ -1576,6 +1593,7 @@ void adjustOpenFilesLimit(void);
...
@@ -1576,6 +1593,7 @@ void adjustOpenFilesLimit(void);
void
closeListeningSockets
(
int
unlink_unix_socket
);
void
closeListeningSockets
(
int
unlink_unix_socket
);
void
updateCachedTime
(
void
);
void
updateCachedTime
(
void
);
void
resetServerStats
(
void
);
void
resetServerStats
(
void
);
void
activeDefragCycle
(
void
);
unsigned
int
getLRUClock
(
void
);
unsigned
int
getLRUClock
(
void
);
const
char
*
evictPolicyToString
(
void
);
const
char
*
evictPolicyToString
(
void
);
struct
redisMemOverhead
*
getMemoryOverheadData
(
void
);
struct
redisMemOverhead
*
getMemoryOverheadData
(
void
);
...
...
src/zmalloc.c
View file @
7aa9e6d2
...
@@ -66,6 +66,8 @@ void zlibc_free(void *ptr) {
...
@@ -66,6 +66,8 @@ void zlibc_free(void *ptr) {
#define calloc(count,size) je_calloc(count,size)
#define calloc(count,size) je_calloc(count,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define realloc(ptr,size) je_realloc(ptr,size)
#define free(ptr) je_free(ptr)
#define free(ptr) je_free(ptr)
#define mallocx(size,flags) je_mallocx(size,flags)
#define dallocx(ptr,flags) je_dallocx(ptr,flags)
#endif
#endif
#define update_zmalloc_stat_alloc(__n) do { \
#define update_zmalloc_stat_alloc(__n) do { \
...
@@ -115,6 +117,24 @@ void *zmalloc(size_t size) {
...
@@ -115,6 +117,24 @@ void *zmalloc(size_t size) {
#endif
#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
*
zcalloc
(
size_t
size
)
{
void
*
ptr
=
calloc
(
1
,
size
+
PREFIX_SIZE
);
void
*
ptr
=
calloc
(
1
,
size
+
PREFIX_SIZE
);
...
...
src/zmalloc.h
View file @
7aa9e6d2
...
@@ -69,6 +69,8 @@ void *zmalloc(size_t size);
...
@@ -69,6 +69,8 @@ void *zmalloc(size_t size);
void
*
zcalloc
(
size_t
size
);
void
*
zcalloc
(
size_t
size
);
void
*
zrealloc
(
void
*
ptr
,
size_t
size
);
void
*
zrealloc
(
void
*
ptr
,
size_t
size
);
void
zfree
(
void
*
ptr
);
void
zfree
(
void
*
ptr
);
void
zfree_no_tcache
(
void
*
ptr
);
void
*
zmalloc_no_tcache
(
size_t
size
);
char
*
zstrdup
(
const
char
*
s
);
char
*
zstrdup
(
const
char
*
s
);
size_t
zmalloc_used_memory
(
void
);
size_t
zmalloc_used_memory
(
void
);
void
zmalloc_enable_thread_safeness
(
void
);
void
zmalloc_enable_thread_safeness
(
void
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment