mirror of
https://github.com/redis/redis.git
synced 2026-04-21 03:01:35 -04:00
Created specific SMEMBERS command logic which avoids sinterGenericCommand, and minimizes processing and memory overhead (#13499)
This PR introduces a dedicated implementation for the SMEMBERS command that avoids using the more generalized sinterGenericCommand function. By tailoring the logic specifically for SMEMBERS, we reduce unnecessary processing and memory overheads that were previously incurred by handling more complex cases like set intersections. --------- Co-authored-by: debing.sun <debing.sun@redis.com>
This commit is contained in:
committed by
GitHub
parent
a31b516e25
commit
00a8e72cfc
@@ -11145,7 +11145,7 @@ struct COMMAND_STRUCT redisCommandTable[] = {
|
||||
{MAKE_CMD("sintercard","Returns the number of members of the intersect of multiple sets.","O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.","7.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SINTERCARD_History,0,SINTERCARD_Tips,0,sinterCardCommand,-3,CMD_READONLY,ACL_CATEGORY_SET,SINTERCARD_Keyspecs,1,sintercardGetKeys,3),.args=SINTERCARD_Args},
|
||||
{MAKE_CMD("sinterstore","Stores the intersect of multiple sets in a key.","O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SINTERSTORE_History,0,SINTERSTORE_Tips,0,sinterstoreCommand,-3,CMD_WRITE|CMD_DENYOOM,ACL_CATEGORY_SET,SINTERSTORE_Keyspecs,2,NULL,2),.args=SINTERSTORE_Args},
|
||||
{MAKE_CMD("sismember","Determines whether a member belongs to a set.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SISMEMBER_History,0,SISMEMBER_Tips,0,sismemberCommand,3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_SET,SISMEMBER_Keyspecs,1,NULL,2),.args=SISMEMBER_Args},
|
||||
{MAKE_CMD("smembers","Returns all members of a set.","O(N) where N is the set cardinality.","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SMEMBERS_History,0,SMEMBERS_Tips,1,sinterCommand,2,CMD_READONLY,ACL_CATEGORY_SET,SMEMBERS_Keyspecs,1,NULL,1),.args=SMEMBERS_Args},
|
||||
{MAKE_CMD("smembers","Returns all members of a set.","O(N) where N is the set cardinality.","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SMEMBERS_History,0,SMEMBERS_Tips,1,smembersCommand,2,CMD_READONLY,ACL_CATEGORY_SET,SMEMBERS_Keyspecs,1,NULL,1),.args=SMEMBERS_Args},
|
||||
{MAKE_CMD("smismember","Determines whether multiple members belong to a set.","O(N) where N is the number of elements being checked for membership","6.2.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SMISMEMBER_History,0,SMISMEMBER_Tips,0,smismemberCommand,-3,CMD_READONLY|CMD_FAST,ACL_CATEGORY_SET,SMISMEMBER_Keyspecs,1,NULL,2),.args=SMISMEMBER_Args},
|
||||
{MAKE_CMD("smove","Moves a member from one set to another.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SMOVE_History,0,SMOVE_Tips,0,smoveCommand,4,CMD_WRITE|CMD_FAST,ACL_CATEGORY_SET,SMOVE_Keyspecs,2,NULL,3),.args=SMOVE_Args},
|
||||
{MAKE_CMD("spop","Returns one or more random members from a set after removing them. Deletes the set if the last member was popped.","Without the count argument O(1), otherwise O(N) where N is the value of the passed count.","1.0.0",CMD_DOC_NONE,NULL,NULL,"set",COMMAND_GROUP_SET,SPOP_History,1,SPOP_Tips,1,spopCommand,-2,CMD_WRITE|CMD_FAST,ACL_CATEGORY_SET,SPOP_Keyspecs,1,NULL,2),.args=SPOP_Args},
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"group": "set",
|
||||
"since": "1.0.0",
|
||||
"arity": 2,
|
||||
"function": "sinterCommand",
|
||||
"function": "smembersCommand",
|
||||
"command_flags": [
|
||||
"READONLY"
|
||||
],
|
||||
|
||||
@@ -3639,6 +3639,7 @@ void scardCommand(client *c);
|
||||
void spopCommand(client *c);
|
||||
void srandmemberCommand(client *c);
|
||||
void sinterCommand(client *c);
|
||||
void smembersCommand(client *c);
|
||||
void sinterCardCommand(client *c);
|
||||
void sinterstoreCommand(client *c);
|
||||
void sunionCommand(client *c);
|
||||
|
||||
29
src/t_set.c
29
src/t_set.c
@@ -1244,7 +1244,7 @@ int qsortCompareSetsByRevCardinality(const void *s1, const void *s2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SINTER / SMEMBERS / SINTERSTORE / SINTERCARD
|
||||
/* SINTER / SINTERSTORE / SINTERCARD
|
||||
*
|
||||
* 'cardinality_only' work for SINTERCARD, only return the cardinality
|
||||
* with minimum processing and memory overheads.
|
||||
@@ -1420,6 +1420,33 @@ void sinterCommand(client *c) {
|
||||
sinterGenericCommand(c, c->argv+1, c->argc-1, NULL, 0, 0);
|
||||
}
|
||||
|
||||
/* SMEMBERS key */
|
||||
void smembersCommand(client *c) {
|
||||
setTypeIterator *si;
|
||||
char *str;
|
||||
size_t len;
|
||||
int64_t intobj;
|
||||
robj *setobj = lookupKeyRead(c->db, c->argv[1]);
|
||||
if (checkType(c,setobj,OBJ_SET)) return;
|
||||
if (!setobj) {
|
||||
addReply(c, shared.emptyset[c->resp]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare the response. */
|
||||
addReplySetLen(c,setTypeSize(setobj));
|
||||
|
||||
/* Iterate through the elements of the set. */
|
||||
si = setTypeInitIterator(setobj);
|
||||
while (setTypeNext(si, &str, &len, &intobj) != -1) {
|
||||
if (str != NULL)
|
||||
addReplyBulkCBuffer(c, str, len);
|
||||
else
|
||||
addReplyBulkLongLong(c, intobj);
|
||||
}
|
||||
setTypeReleaseIterator(si);
|
||||
}
|
||||
|
||||
/* SINTERCARD numkeys key [key ...] [LIMIT limit] */
|
||||
void sinterCardCommand(client *c) {
|
||||
long j;
|
||||
|
||||
Reference in New Issue
Block a user