Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
d0686e07
Commit
d0686e07
authored
Jun 04, 2010
by
Pieter Noordhuis
Browse files
add thresholds for converting a ziplist to a real list
parent
846d8b3e
Changes
1
Hide whitespace changes
Inline
Side-by-side
redis.c
View file @
d0686e07
...
@@ -237,9 +237,11 @@ static char* strencoding[] = {
...
@@ -237,9 +237,11 @@ static char* strencoding[] = {
#define APPENDFSYNC_ALWAYS 1
#define APPENDFSYNC_ALWAYS 1
#define APPENDFSYNC_EVERYSEC 2
#define APPENDFSYNC_EVERYSEC 2
/*
Hashes
related defaults */
/*
Zip structure
related defaults */
#define REDIS_HASH_MAX_ZIPMAP_ENTRIES 64
#define REDIS_HASH_MAX_ZIPMAP_ENTRIES 64
#define REDIS_HASH_MAX_ZIPMAP_VALUE 512
#define REDIS_HASH_MAX_ZIPMAP_VALUE 512
#define REDIS_LIST_MAX_ZIPLIST_ENTRIES 1024
#define REDIS_LIST_MAX_ZIPLIST_VALUE 32
/* We can print the stacktrace, so our assert is defined this way: */
/* We can print the stacktrace, so our assert is defined this way: */
#define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))
#define redisAssert(_e) ((_e)?(void)0 : (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))
...
@@ -425,9 +427,11 @@ struct redisServer {
...
@@ -425,9 +427,11 @@ struct redisServer {
off_t
vm_page_size
;
off_t
vm_page_size
;
off_t
vm_pages
;
off_t
vm_pages
;
unsigned
long
long
vm_max_memory
;
unsigned
long
long
vm_max_memory
;
/*
Hashes
config */
/*
Zip structure
config */
size_t
hash_max_zipmap_entries
;
size_t
hash_max_zipmap_entries
;
size_t
hash_max_zipmap_value
;
size_t
hash_max_zipmap_value
;
size_t
list_max_ziplist_entries
;
size_t
list_max_ziplist_value
;
/* Virtual memory state */
/* Virtual memory state */
FILE
*
vm_fp
;
FILE
*
vm_fp
;
int
vm_fd
;
int
vm_fd
;
...
@@ -646,6 +650,7 @@ static struct redisCommand *lookupCommand(char *name);
...
@@ -646,6 +650,7 @@ static struct redisCommand *lookupCommand(char *name);
static
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
static
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
static
void
resetClient
(
redisClient
*
c
);
static
void
resetClient
(
redisClient
*
c
);
static
void
convertToRealHash
(
robj
*
o
);
static
void
convertToRealHash
(
robj
*
o
);
static
void
convertList
(
robj
*
o
,
int
enc
);
static
int
pubsubUnsubscribeAllChannels
(
redisClient
*
c
,
int
notify
);
static
int
pubsubUnsubscribeAllChannels
(
redisClient
*
c
,
int
notify
);
static
int
pubsubUnsubscribeAllPatterns
(
redisClient
*
c
,
int
notify
);
static
int
pubsubUnsubscribeAllPatterns
(
redisClient
*
c
,
int
notify
);
static
void
freePubsubPattern
(
void
*
p
);
static
void
freePubsubPattern
(
void
*
p
);
...
@@ -1755,6 +1760,8 @@ static void initServerConfig() {
...
@@ -1755,6 +1760,8 @@ static void initServerConfig() {
server
.
vm_blocked_clients
=
0
;
server
.
vm_blocked_clients
=
0
;
server
.
hash_max_zipmap_entries
=
REDIS_HASH_MAX_ZIPMAP_ENTRIES
;
server
.
hash_max_zipmap_entries
=
REDIS_HASH_MAX_ZIPMAP_ENTRIES
;
server
.
hash_max_zipmap_value
=
REDIS_HASH_MAX_ZIPMAP_VALUE
;
server
.
hash_max_zipmap_value
=
REDIS_HASH_MAX_ZIPMAP_VALUE
;
server
.
list_max_ziplist_entries
=
REDIS_LIST_MAX_ZIPLIST_ENTRIES
;
server
.
list_max_ziplist_value
=
REDIS_LIST_MAX_ZIPLIST_VALUE
;
server
.
shutdown_asap
=
0
;
server
.
shutdown_asap
=
0
;
resetServerSaveParams
();
resetServerSaveParams
();
...
@@ -2033,6 +2040,10 @@ static void loadServerConfig(char *filename) {
...
@@ -2033,6 +2040,10 @@ static void loadServerConfig(char *filename) {
server
.
hash_max_zipmap_entries
=
memtoll
(
argv
[
1
],
NULL
);
server
.
hash_max_zipmap_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-zipmap-value"
)
&&
argc
==
2
){
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"hash-max-zipmap-value"
)
&&
argc
==
2
){
server
.
hash_max_zipmap_value
=
memtoll
(
argv
[
1
],
NULL
);
server
.
hash_max_zipmap_value
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"list-max-ziplist-entries"
)
&&
argc
==
2
){
server
.
list_max_ziplist_entries
=
memtoll
(
argv
[
1
],
NULL
);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"list-max-ziplist-value"
)
&&
argc
==
2
){
server
.
list_max_ziplist_value
=
memtoll
(
argv
[
1
],
NULL
);
}
else
{
}
else
{
err
=
"Bad directive or wrong number of arguments"
;
goto
loaderr
;
err
=
"Bad directive or wrong number of arguments"
;
goto
loaderr
;
}
}
...
@@ -4154,12 +4165,24 @@ static robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -4154,12 +4165,24 @@ static robj *rdbLoadObject(int type, FILE *fp) {
/* Read list value */
/* Read list value */
if
((
len
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
if
((
len
=
rdbLoadLen
(
fp
,
NULL
))
==
REDIS_RDB_LENERR
)
return
NULL
;
o = createZiplistObject();
/* Use a real list when there are too many entries */
if
(
len
>
server
.
list_max_ziplist_entries
)
{
o
=
createListObject
();
}
else
{
o
=
createZiplistObject
();
}
/* Load every single element of the list */
/* Load every single element of the list */
while
(
len
--
)
{
while
(
len
--
)
{
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadEncodedStringObject
(
fp
))
==
NULL
)
return
NULL
;
/* If we are using a ziplist and the value is too big, convert
* the object to a real list. */
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
&&
ele
->
encoding
==
REDIS_ENCODING_RAW
&&
sdslen
(
ele
->
ptr
)
>
server
.
list_max_ziplist_value
)
convertList
(
o
,
REDIS_ENCODING_LIST
);
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
dec
=
getDecodedObject
(
ele
);
dec
=
getDecodedObject
(
ele
);
o
->
ptr
=
ziplistPush
(
o
->
ptr
,
dec
->
ptr
,
sdslen
(
dec
->
ptr
),
REDIS_TAIL
);
o
->
ptr
=
ziplistPush
(
o
->
ptr
,
dec
->
ptr
,
sdslen
(
dec
->
ptr
),
REDIS_TAIL
);
...
@@ -4882,7 +4905,25 @@ static void moveCommand(redisClient *c) {
...
@@ -4882,7 +4905,25 @@ static void moveCommand(redisClient *c) {
}
}
/* =================================== Lists ================================ */
/* =================================== Lists ================================ */
/* Check the argument length to see if it requires us to convert the ziplist
* to a real list. Only check raw-encoded objects because integer encoded
* objects are never too long. */
static
void
listTryConversion
(
robj
*
subject
,
robj
*
value
)
{
if
(
subject
->
encoding
!=
REDIS_ENCODING_ZIPLIST
)
return
;
if
(
value
->
encoding
==
REDIS_ENCODING_RAW
&&
sdslen
(
value
->
ptr
)
>
server
.
list_max_ziplist_value
)
convertList
(
subject
,
REDIS_ENCODING_LIST
);
}
static
void
lPush
(
robj
*
subject
,
robj
*
value
,
int
where
)
{
static
void
lPush
(
robj
*
subject
,
robj
*
value
,
int
where
)
{
/* Check if we need to convert the ziplist */
listTryConversion
(
subject
,
value
);
if
(
subject
->
encoding
==
REDIS_ENCODING_ZIPLIST
&&
ziplistLen
(
subject
->
ptr
)
>
server
.
list_max_ziplist_entries
)
convertList
(
subject
,
REDIS_ENCODING_LIST
);
if
(
subject
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
if
(
subject
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
int
pos
=
(
where
==
REDIS_HEAD
)
?
ZIPLIST_HEAD
:
ZIPLIST_TAIL
;
int
pos
=
(
where
==
REDIS_HEAD
)
?
ZIPLIST_HEAD
:
ZIPLIST_TAIL
;
value
=
getDecodedObject
(
value
);
value
=
getDecodedObject
(
value
);
...
@@ -5077,6 +5118,27 @@ static void lDelete(lEntry *entry) {
...
@@ -5077,6 +5118,27 @@ static void lDelete(lEntry *entry) {
}
}
}
}
static
void
convertList
(
robj
*
subject
,
int
enc
)
{
lIterator
*
li
;
lEntry
entry
;
redisAssert
(
subject
->
type
==
REDIS_LIST
);
if
(
enc
==
REDIS_ENCODING_LIST
)
{
list
*
l
=
listCreate
();
/* lGet returns a robj with incremented refcount */
li
=
lInitIterator
(
subject
,
0
,
REDIS_TAIL
);
while
(
lNext
(
li
,
&
entry
))
listAddNodeTail
(
l
,
lGet
(
&
entry
));
lReleaseIterator
(
li
);
subject
->
encoding
=
REDIS_ENCODING_LIST
;
zfree
(
subject
->
ptr
);
subject
->
ptr
=
l
;
}
else
{
redisPanic
(
"Unsupported list conversion"
);
}
}
static
void
pushGenericCommand
(
redisClient
*
c
,
int
where
)
{
static
void
pushGenericCommand
(
redisClient
*
c
,
int
where
)
{
robj
*
lobj
=
lookupKeyWrite
(
c
->
db
,
c
->
argv
[
1
]);
robj
*
lobj
=
lookupKeyWrite
(
c
->
db
,
c
->
argv
[
1
]);
if
(
lobj
==
NULL
)
{
if
(
lobj
==
NULL
)
{
...
@@ -5157,6 +5219,7 @@ static void lsetCommand(redisClient *c) {
...
@@ -5157,6 +5219,7 @@ static void lsetCommand(redisClient *c) {
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
int
index
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
robj
*
value
=
c
->
argv
[
3
];
robj
*
value
=
c
->
argv
[
3
];
listTryConversion
(
o
,
value
);
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
if
(
o
->
encoding
==
REDIS_ENCODING_ZIPLIST
)
{
unsigned
char
*
p
,
*
zl
=
o
->
ptr
;
unsigned
char
*
p
,
*
zl
=
o
->
ptr
;
p
=
ziplistIndex
(
zl
,
index
);
p
=
ziplistIndex
(
zl
,
index
);
...
...
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