summaryrefslogtreecommitdiff
path: root/src/t_set.c
diff options
context:
space:
mode:
authorOran Agra <oran@redislabs.com>2023-05-15 13:08:15 +0300
committerGitHub <noreply@github.com>2023-05-15 13:08:15 +0300
commita51eb05b1895babb17c37c36b963e2bcbd5496d5 (patch)
tree7be24b09e0a5621a03e9f9ffe9ef27fcb44d8345 /src/t_set.c
parente26a769d9627ebecb8607375580970a740348956 (diff)
parent986dbf716e0cb904c80bb444635cea3242859cc1 (diff)
downloadredis-7.2.tar.gz
Release Redis 7.2 RC27.2-rc27.2
Diffstat (limited to 'src/t_set.c')
-rw-r--r--src/t_set.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/t_set.c b/src/t_set.c
index ba32ae51c..56ad95a53 100644
--- a/src/t_set.c
+++ b/src/t_set.c
@@ -39,11 +39,31 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
/* Factory method to return a set that *can* hold "value". When the object has
* an integer-encodable value, an intset will be returned. Otherwise a regular
- * hash table. */
-robj *setTypeCreate(sds value) {
- if (isSdsRepresentableAsLongLong(value,NULL) == C_OK)
+ * hash table.
+ *
+ * The size hint indicates approximately how many items will be added which is
+ * used to determine the initial representation. */
+robj *setTypeCreate(sds value, size_t size_hint) {
+ if (isSdsRepresentableAsLongLong(value,NULL) == C_OK && size_hint < server.set_max_intset_entries)
return createIntsetObject();
- return createSetListpackObject();
+ if (size_hint < server.set_max_listpack_entries)
+ return createSetListpackObject();
+
+ /* We may oversize the set by using the hint if the hint is not accurate,
+ * but we will assume this is accpetable to maximize performance. */
+ robj *o = createSetObject();
+ dictExpand(o->ptr, size_hint);
+ return o;
+}
+
+/* Check if the existing set should be converted to another encoding based off the
+ * the size hint. */
+void setTypeMaybeConvert(robj *set, size_t size_hint) {
+ if ((set->encoding == OBJ_ENCODING_LISTPACK && size_hint >= server.set_max_listpack_entries)
+ || (set->encoding == OBJ_ENCODING_INTSET && size_hint >= server.set_max_intset_entries))
+ {
+ setTypeConvertAndExpand(set, OBJ_ENCODING_HT, size_hint, 1);
+ }
}
/* Return the maximum number of entries to store in an intset. */
@@ -590,8 +610,10 @@ void saddCommand(client *c) {
if (checkType(c,set,OBJ_SET)) return;
if (set == NULL) {
- set = setTypeCreate(c->argv[2]->ptr);
+ set = setTypeCreate(c->argv[2]->ptr, c->argc - 2);
dbAdd(c->db,c->argv[1],set);
+ } else {
+ setTypeMaybeConvert(set, c->argc - 2);
}
for (j = 2; j < c->argc; j++) {
@@ -672,7 +694,7 @@ void smoveCommand(client *c) {
/* Create the destination set when it doesn't exist */
if (!dstset) {
- dstset = setTypeCreate(ele->ptr);
+ dstset = setTypeCreate(ele->ptr, 1);
dbAdd(c->db,c->argv[2],dstset);
}