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
05df7621
Commit
05df7621
authored
Apr 12, 2010
by
antirez
Browse files
Sharing of small integer objects: may save a lot of memory with datasets having many of this
parent
dae121d9
Changes
1
Show whitespace changes
Inline
Side-by-side
redis.c
View file @
05df7621
...
@@ -505,6 +505,7 @@ typedef struct zset {
...
@@ -505,6 +505,7 @@ typedef struct zset {
/* Our shared "common" objects */
/* Our shared "common" objects */
#define REDIS_SHARED_INTEGERS 10000
struct
sharedObjectsStruct
{
struct
sharedObjectsStruct
{
robj
*
crlf
,
*
ok
,
*
err
,
*
emptybulk
,
*
czero
,
*
cone
,
*
pong
,
*
space
,
robj
*
crlf
,
*
ok
,
*
err
,
*
emptybulk
,
*
czero
,
*
cone
,
*
pong
,
*
space
,
*
colon
,
*
nullbulk
,
*
nullmultibulk
,
*
queued
,
*
colon
,
*
nullbulk
,
*
nullmultibulk
,
*
queued
,
...
@@ -513,7 +514,7 @@ struct sharedObjectsStruct {
...
@@ -513,7 +514,7 @@ struct sharedObjectsStruct {
*
select0
,
*
select1
,
*
select2
,
*
select3
,
*
select4
,
*
select0
,
*
select1
,
*
select2
,
*
select3
,
*
select4
,
*
select5
,
*
select6
,
*
select7
,
*
select8
,
*
select9
,
*
select5
,
*
select6
,
*
select7
,
*
select8
,
*
select9
,
*
messagebulk
,
*
subscribebulk
,
*
unsubscribebulk
,
*
mbulk3
,
*
messagebulk
,
*
subscribebulk
,
*
unsubscribebulk
,
*
mbulk3
,
*psubscribebulk, *punsubscribebulk;
*
psubscribebulk
,
*
punsubscribebulk
,
*
integers
[
REDIS_SHARED_INTEGERS
]
;
}
shared
;
}
shared
;
/* Global vars that are actally used as constants. The following double
/* Global vars that are actally used as constants. The following double
...
@@ -556,7 +557,7 @@ static robj *dupStringObject(robj *o);
...
@@ -556,7 +557,7 @@ static robj *dupStringObject(robj *o);
static
void
replicationFeedSlaves
(
list
*
slaves
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
void
replicationFeedSlaves
(
list
*
slaves
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
void
feedAppendOnlyFile
(
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
void
feedAppendOnlyFile
(
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
);
static
int
syncWithMaster
(
void
);
static
int
syncWithMaster
(
void
);
static
int
tryObjectEncoding(robj *o);
static
robj
*
tryObjectEncoding
(
robj
*
o
);
static
robj
*
getDecodedObject
(
robj
*
o
);
static
robj
*
getDecodedObject
(
robj
*
o
);
static
int
removeExpire
(
redisDb
*
db
,
robj
*
key
);
static
int
removeExpire
(
redisDb
*
db
,
robj
*
key
);
static
int
expireIfNeeded
(
redisDb
*
db
,
robj
*
key
);
static
int
expireIfNeeded
(
redisDb
*
db
,
robj
*
key
);
...
@@ -1484,6 +1485,8 @@ static void beforeSleep(struct aeEventLoop *eventLoop) {
...
@@ -1484,6 +1485,8 @@ static void beforeSleep(struct aeEventLoop *eventLoop) {
}
}
static
void
createSharedObjects
(
void
)
{
static
void
createSharedObjects
(
void
)
{
int
j
;
shared
.
crlf
=
createObject
(
REDIS_STRING
,
sdsnew
(
"
\r\n
"
));
shared
.
crlf
=
createObject
(
REDIS_STRING
,
sdsnew
(
"
\r\n
"
));
shared
.
ok
=
createObject
(
REDIS_STRING
,
sdsnew
(
"+OK
\r\n
"
));
shared
.
ok
=
createObject
(
REDIS_STRING
,
sdsnew
(
"+OK
\r\n
"
));
shared
.
err
=
createObject
(
REDIS_STRING
,
sdsnew
(
"-ERR
\r\n
"
));
shared
.
err
=
createObject
(
REDIS_STRING
,
sdsnew
(
"-ERR
\r\n
"
));
...
@@ -1524,6 +1527,10 @@ static void createSharedObjects(void) {
...
@@ -1524,6 +1527,10 @@ static void createSharedObjects(void) {
shared
.
psubscribebulk
=
createStringObject
(
"$10
\r\n
psubscribe
\r\n
"
,
17
);
shared
.
psubscribebulk
=
createStringObject
(
"$10
\r\n
psubscribe
\r\n
"
,
17
);
shared
.
punsubscribebulk
=
createStringObject
(
"$12
\r\n
punsubscribe
\r\n
"
,
19
);
shared
.
punsubscribebulk
=
createStringObject
(
"$12
\r\n
punsubscribe
\r\n
"
,
19
);
shared
.
mbulk3
=
createStringObject
(
"*3
\r\n
"
,
4
);
shared
.
mbulk3
=
createStringObject
(
"*3
\r\n
"
,
4
);
for
(
j
=
0
;
j
<
REDIS_SHARED_INTEGERS
;
j
++
)
{
shared
.
integers
[
j
]
=
createObject
(
REDIS_STRING
,(
void
*
)(
long
)
j
);
shared
.
integers
[
j
]
->
encoding
=
REDIS_ENCODING_INT
;
}
}
}
static
void
appendServerSaveParams
(
time_t
seconds
,
int
changes
)
{
static
void
appendServerSaveParams
(
time_t
seconds
,
int
changes
)
{
...
@@ -2277,7 +2284,7 @@ static int processCommand(redisClient *c) {
...
@@ -2277,7 +2284,7 @@ static int processCommand(redisClient *c) {
}
}
/* Let's try to encode the bulk object to save space. */
/* Let's try to encode the bulk object to save space. */
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
tryObjectEncoding(c->argv[c->argc-1]);
c
->
argv
[
c
->
argc
-
1
]
=
tryObjectEncoding
(
c
->
argv
[
c
->
argc
-
1
]);
/* Check if the user is authenticated */
/* Check if the user is authenticated */
if
(
server
.
requirepass
&&
!
c
->
authenticated
&&
cmd
->
proc
!=
authCommand
)
{
if
(
server
.
requirepass
&&
!
c
->
authenticated
&&
cmd
->
proc
!=
authCommand
)
{
...
@@ -2963,29 +2970,35 @@ static int isStringRepresentableAsLong(sds s, long *longval) {
...
@@ -2963,29 +2970,35 @@ static int isStringRepresentableAsLong(sds s, long *longval) {
}
}
/* Try to encode a string object in order to save space */
/* Try to encode a string object in order to save space */
static
int
tryObjectEncoding(robj *o) {
static
robj
*
tryObjectEncoding
(
robj
*
o
)
{
long
value
;
long
value
;
sds
s
=
o
->
ptr
;
sds
s
=
o
->
ptr
;
if
(
o
->
encoding
!=
REDIS_ENCODING_RAW
)
if
(
o
->
encoding
!=
REDIS_ENCODING_RAW
)
return
REDIS_ERR
; /* Already encoded */
return
o
;
/* Already encoded */
/* It's not sa
v
e to encode shared objects: shared objects can be shared
/* It's not sa
f
e to encode shared objects: shared objects can be shared
* everywhere in the "object space" of Redis. Encoded objects can only
* everywhere in the "object space" of Redis. Encoded objects can only
* appear as "values" (and not, for instance, as keys) */
* appear as "values" (and not, for instance, as keys) */
if (o->refcount > 1) return
REDIS_ERR
;
if
(
o
->
refcount
>
1
)
return
o
;
/* Currently we try to encode only strings */
/* Currently we try to encode only strings */
redisAssert
(
o
->
type
==
REDIS_STRING
);
redisAssert
(
o
->
type
==
REDIS_STRING
);
/* Check if we can represent this string as a long integer */
/* Check if we can represent this string as a long integer */
if (isStringRepresentableAsLong(s,&value) == REDIS_ERR) return
REDIS_ERR
;
if
(
isStringRepresentableAsLong
(
s
,
&
value
)
==
REDIS_ERR
)
return
o
;
/* Ok, this object can be encoded */
/* Ok, this object can be encoded */
if
(
value
>=
0
&&
value
<
REDIS_SHARED_INTEGERS
)
{
decrRefCount
(
o
);
incrRefCount
(
shared
.
integers
[
value
]);
return
shared
.
integers
[
value
];
}
else
{
o
->
encoding
=
REDIS_ENCODING_INT
;
o
->
encoding
=
REDIS_ENCODING_INT
;
sdsfree
(
o
->
ptr
);
sdsfree
(
o
->
ptr
);
o
->
ptr
=
(
void
*
)
value
;
o
->
ptr
=
(
void
*
)
value
;
return REDIS_OK;
return
o
;
}
}
}
/* Get a decoded version of an encoded object (returned as a new object).
/* Get a decoded version of an encoded object (returned as a new object).
...
@@ -3603,7 +3616,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -3603,7 +3616,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
if
(
type
==
REDIS_STRING
)
{
if
(
type
==
REDIS_STRING
)
{
/* Read string value */
/* Read string value */
if
((
o
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
o
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
tryObjectEncoding(o);
o
=
tryObjectEncoding
(
o
);
}
else
if
(
type
==
REDIS_LIST
||
type
==
REDIS_SET
)
{
}
else
if
(
type
==
REDIS_LIST
||
type
==
REDIS_SET
)
{
/* Read list/set value */
/* Read list/set value */
uint32_t
listlen
;
uint32_t
listlen
;
...
@@ -3619,7 +3632,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -3619,7 +3632,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
robj
*
ele
;
robj
*
ele
;
if
((
ele
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
tryObjectEncoding(ele);
ele
=
tryObjectEncoding
(
ele
);
if
(
type
==
REDIS_LIST
)
{
if
(
type
==
REDIS_LIST
)
{
listAddNodeTail
((
list
*
)
o
->
ptr
,
ele
);
listAddNodeTail
((
list
*
)
o
->
ptr
,
ele
);
}
else
{
}
else
{
...
@@ -3640,7 +3653,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -3640,7 +3653,7 @@ static robj *rdbLoadObject(int type, FILE *fp) {
double
*
score
=
zmalloc
(
sizeof
(
double
));
double
*
score
=
zmalloc
(
sizeof
(
double
));
if
((
ele
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
if
((
ele
=
rdbLoadStringObject
(
fp
))
==
NULL
)
return
NULL
;
tryObjectEncoding(ele);
ele
=
tryObjectEncoding
(
ele
);
if
(
rdbLoadDoubleValue
(
fp
,
score
)
==
-
1
)
return
NULL
;
if
(
rdbLoadDoubleValue
(
fp
,
score
)
==
-
1
)
return
NULL
;
dictAdd
(
zs
->
dict
,
ele
,
score
);
dictAdd
(
zs
->
dict
,
ele
,
score
);
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
zslInsert
(
zs
->
zsl
,
*
score
,
ele
);
...
@@ -3679,8 +3692,8 @@ static robj *rdbLoadObject(int type, FILE *fp) {
...
@@ -3679,8 +3692,8 @@ static robj *rdbLoadObject(int type, FILE *fp) {
decrRefCount
(
key
);
decrRefCount
(
key
);
decrRefCount
(
val
);
decrRefCount
(
val
);
}
else
{
}
else
{
tryObjectEncoding(key);
key
=
tryObjectEncoding
(
key
);
tryObjectEncoding(val);
val
=
tryObjectEncoding
(
val
);
dictAdd
((
dict
*
)
o
->
ptr
,
key
,
val
);
dictAdd
((
dict
*
)
o
->
ptr
,
key
,
val
);
}
}
}
}
...
@@ -3906,7 +3919,7 @@ static void msetGenericCommand(redisClient *c, int nx) {
...
@@ -3906,7 +3919,7 @@ static void msetGenericCommand(redisClient *c, int nx) {
for
(
j
=
1
;
j
<
c
->
argc
;
j
+=
2
)
{
for
(
j
=
1
;
j
<
c
->
argc
;
j
+=
2
)
{
int
retval
;
int
retval
;
tryObjectEncoding(c->argv[j+1]);
c
->
argv
[
j
+
1
]
=
tryObjectEncoding
(
c
->
argv
[
j
+
1
]);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
if
(
retval
==
DICT_ERR
)
{
if
(
retval
==
DICT_ERR
)
{
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
j
],
c
->
argv
[
j
+
1
]);
...
@@ -3954,7 +3967,7 @@ static void incrDecrCommand(redisClient *c, long long incr) {
...
@@ -3954,7 +3967,7 @@ static void incrDecrCommand(redisClient *c, long long incr) {
value
+=
incr
;
value
+=
incr
;
o
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
o
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
tryObjectEncoding(o);
o
=
tryObjectEncoding
(
o
);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
retval
=
dictAdd
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
if
(
retval
==
DICT_ERR
)
{
if
(
retval
==
DICT_ERR
)
{
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
dictReplace
(
c
->
db
->
dict
,
c
->
argv
[
1
],
o
);
...
@@ -5977,7 +5990,7 @@ static void hsetCommand(redisClient *c) {
...
@@ -5977,7 +5990,7 @@ static void hsetCommand(redisClient *c) {
if
(
zipmapLen
(
zm
)
>
server
.
hash_max_zipmap_entries
)
if
(
zipmapLen
(
zm
)
>
server
.
hash_max_zipmap_entries
)
convertToRealHash
(
o
);
convertToRealHash
(
o
);
}
else
{
}
else
{
tryObjectEncoding(c->argv[2]);
c
->
argv
[
2
]
=
tryObjectEncoding
(
c
->
argv
[
2
]);
/* note that c->argv[3] is already encoded, as the latest arg
/* note that c->argv[3] is already encoded, as the latest arg
* of a bulk command is always integer encoded if possible. */
* of a bulk command is always integer encoded if possible. */
if
(
dictReplace
(
o
->
ptr
,
c
->
argv
[
2
],
c
->
argv
[
3
]))
{
if
(
dictReplace
(
o
->
ptr
,
c
->
argv
[
2
],
c
->
argv
[
3
]))
{
...
@@ -6050,7 +6063,7 @@ static void hincrbyCommand(redisClient *c) {
...
@@ -6050,7 +6063,7 @@ static void hincrbyCommand(redisClient *c) {
value
+=
incr
;
value
+=
incr
;
hval
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
hval
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%lld"
,
value
));
tryObjectEncoding(hval);
hval
=
tryObjectEncoding
(
hval
);
if
(
dictReplace
(
o
->
ptr
,
c
->
argv
[
2
],
hval
))
{
if
(
dictReplace
(
o
->
ptr
,
c
->
argv
[
2
],
hval
))
{
incrRefCount
(
c
->
argv
[
2
]);
incrRefCount
(
c
->
argv
[
2
]);
}
}
...
@@ -6235,8 +6248,8 @@ static void convertToRealHash(robj *o) {
...
@@ -6235,8 +6248,8 @@ static void convertToRealHash(robj *o) {
keyobj
=
createStringObject
((
char
*
)
key
,
klen
);
keyobj
=
createStringObject
((
char
*
)
key
,
klen
);
valobj
=
createStringObject
((
char
*
)
val
,
vlen
);
valobj
=
createStringObject
((
char
*
)
val
,
vlen
);
tryObjectEncoding(keyobj);
keyobj
=
tryObjectEncoding
(
keyobj
);
tryObjectEncoding(valobj);
valobj
=
tryObjectEncoding
(
valobj
);
dictAdd
(
dict
,
keyobj
,
valobj
);
dictAdd
(
dict
,
keyobj
,
valobj
);
}
}
o
->
encoding
=
REDIS_ENCODING_HT
;
o
->
encoding
=
REDIS_ENCODING_HT
;
...
@@ -7748,7 +7761,7 @@ int loadAppendOnlyFile(char *filename) {
...
@@ -7748,7 +7761,7 @@ int loadAppendOnlyFile(char *filename) {
}
}
/* Try object encoding */
/* Try object encoding */
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
if
(
cmd
->
flags
&
REDIS_CMD_BULK
)
tryObjectEncoding(argv[argc-1]);
argv
[
argc
-
1
]
=
tryObjectEncoding
(
argv
[
argc
-
1
]);
/* Run the command in the context of a fake client */
/* Run the command in the context of a fake client */
fakeClient
->
argc
=
argc
;
fakeClient
->
argc
=
argc
;
fakeClient
->
argv
=
argv
;
fakeClient
->
argv
=
argv
;
...
...
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