Eliminate hashTypeIterator memory allocation by assigning it on stack (#1105)

Signed-off-by: Masahiro Ide <masahiro.ide@lycorp.co.jp>
Signed-off-by: Masahiro Ide <imasahiro9@gmail.com>
Co-authored-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
Co-authored-by: Masahiro Ide <masahiro.ide@lycorp.co.jp>
This commit is contained in:
Masahiro Ide 2024-10-07 04:34:45 +09:00 committed by GitHub
parent a1cc7c263a
commit b5eb793079
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 53 deletions

View File

@ -1947,30 +1947,30 @@ static int rioWriteHashIteratorCursor(rio *r, hashTypeIterator *hi, int what) {
/* Emit the commands needed to rebuild a hash object.
* The function returns 0 on error, 1 on success. */
int rewriteHashObject(rio *r, robj *key, robj *o) {
hashTypeIterator *hi;
hashTypeIterator hi;
long long count = 0, items = hashTypeLength(o);
hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != C_ERR) {
hashTypeInitIterator(o, &hi);
while (hashTypeNext(&hi) != C_ERR) {
if (count == 0) {
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ? AOF_REWRITE_ITEMS_PER_CMD : items;
if (!rioWriteBulkCount(r, '*', 2 + cmd_items * 2) || !rioWriteBulkString(r, "HMSET", 5) ||
!rioWriteBulkObject(r, key)) {
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
return 0;
}
}
if (!rioWriteHashIteratorCursor(r, hi, OBJ_HASH_KEY) || !rioWriteHashIteratorCursor(r, hi, OBJ_HASH_VALUE)) {
hashTypeReleaseIterator(hi);
if (!rioWriteHashIteratorCursor(r, &hi, OBJ_HASH_KEY) || !rioWriteHashIteratorCursor(r, &hi, OBJ_HASH_VALUE)) {
hashTypeResetIterator(&hi);
return 0;
}
if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;
items--;
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
return 1;
}

View File

@ -221,21 +221,22 @@ void xorObjectDigest(serverDb *db, robj *keyobj, unsigned char *digest, robj *o)
serverPanic("Unknown sorted set encoding");
}
} else if (o->type == OBJ_HASH) {
hashTypeIterator *hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != C_ERR) {
hashTypeIterator hi;
hashTypeInitIterator(o, &hi);
while (hashTypeNext(&hi) != C_ERR) {
unsigned char eledigest[20];
sds sdsele;
memset(eledigest, 0, 20);
sdsele = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
sdsele = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
mixDigest(eledigest, sdsele, sdslen(sdsele));
sdsfree(sdsele);
sdsele = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
sdsele = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
mixDigest(eledigest, sdsele, sdslen(sdsele));
sdsfree(sdsele);
xorDigest(digest, eledigest, 20);
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
} else if (o->type == OBJ_STREAM) {
streamIterator si;
streamIteratorStart(&si, o->ptr, NULL, NULL, 0);

View File

@ -2603,7 +2603,7 @@ typedef struct {
unsigned char *fptr, *vptr;
dictIterator *di;
dictIterator di;
dictEntry *de;
} hashTypeIterator;
@ -3370,8 +3370,8 @@ void hashTypeTryConversion(robj *subject, robj **argv, int start, int end);
int hashTypeExists(robj *o, sds key);
int hashTypeDelete(robj *o, sds key);
unsigned long hashTypeLength(const robj *o);
hashTypeIterator *hashTypeInitIterator(robj *subject);
void hashTypeReleaseIterator(hashTypeIterator *hi);
void hashTypeInitIterator(robj *subject, hashTypeIterator *hi);
void hashTypeResetIterator(hashTypeIterator *hi);
int hashTypeNext(hashTypeIterator *hi);
void hashTypeCurrentFromListpack(hashTypeIterator *hi,
int what,

View File

@ -307,8 +307,7 @@ unsigned long hashTypeLength(const robj *o) {
return length;
}
hashTypeIterator *hashTypeInitIterator(robj *subject) {
hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator));
void hashTypeInitIterator(robj *subject, hashTypeIterator *hi) {
hi->subject = subject;
hi->encoding = subject->encoding;
@ -316,16 +315,14 @@ hashTypeIterator *hashTypeInitIterator(robj *subject) {
hi->fptr = NULL;
hi->vptr = NULL;
} else if (hi->encoding == OBJ_ENCODING_HT) {
hi->di = dictGetIterator(subject->ptr);
dictInitIterator(&hi->di, subject->ptr);
} else {
serverPanic("Unknown hash encoding");
}
return hi;
}
void hashTypeReleaseIterator(hashTypeIterator *hi) {
if (hi->encoding == OBJ_ENCODING_HT) dictReleaseIterator(hi->di);
zfree(hi);
void hashTypeResetIterator(hashTypeIterator *hi) {
if (hi->encoding == OBJ_ENCODING_HT) dictResetIterator(&hi->di);
}
/* Move to the next entry in the hash. Return C_OK when the next entry
@ -358,7 +355,7 @@ int hashTypeNext(hashTypeIterator *hi) {
hi->fptr = fptr;
hi->vptr = vptr;
} else if (hi->encoding == OBJ_ENCODING_HT) {
if ((hi->de = dictNext(hi->di)) == NULL) return C_ERR;
if ((hi->de = dictNext(&hi->di)) == NULL) return C_ERR;
} else {
serverPanic("Unknown hash encoding");
}
@ -448,31 +445,31 @@ void hashTypeConvertListpack(robj *o, int enc) {
/* Nothing to do... */
} else if (enc == OBJ_ENCODING_HT) {
hashTypeIterator *hi;
hashTypeIterator hi;
dict *dict;
int ret;
hi = hashTypeInitIterator(o);
hashTypeInitIterator(o, &hi);
dict = dictCreate(&hashDictType);
/* Presize the dict to avoid rehashing */
dictExpand(dict, hashTypeLength(o));
while (hashTypeNext(hi) != C_ERR) {
while (hashTypeNext(&hi) != C_ERR) {
sds key, value;
key = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
value = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
key = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
value = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
ret = dictAdd(dict, key, value);
if (ret != DICT_OK) {
sdsfree(key);
sdsfree(value); /* Needed for gcc ASAN */
hashTypeReleaseIterator(hi); /* Needed for gcc ASAN */
sdsfree(value); /* Needed for gcc ASAN */
hashTypeResetIterator(&hi); /* Needed for gcc ASAN */
serverLogHexDump(LL_WARNING, "listpack with dup elements dump", o->ptr, lpBytes(o->ptr));
serverPanic("Listpack corruption detected");
}
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
zfree(o->ptr);
o->encoding = OBJ_ENCODING_HT;
o->ptr = dict;
@ -498,7 +495,7 @@ void hashTypeConvert(robj *o, int enc) {
* The resulting object always has refcount set to 1 */
robj *hashTypeDup(robj *o) {
robj *hobj;
hashTypeIterator *hi;
hashTypeIterator hi;
serverAssert(o->type == OBJ_HASH);
@ -513,20 +510,20 @@ robj *hashTypeDup(robj *o) {
dict *d = dictCreate(&hashDictType);
dictExpand(d, dictSize((const dict *)o->ptr));
hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != C_ERR) {
hashTypeInitIterator(o, &hi);
while (hashTypeNext(&hi) != C_ERR) {
sds field, value;
sds newfield, newvalue;
/* Extract a field-value pair from an original hash object.*/
field = hashTypeCurrentFromHashTable(hi, OBJ_HASH_KEY);
value = hashTypeCurrentFromHashTable(hi, OBJ_HASH_VALUE);
field = hashTypeCurrentFromHashTable(&hi, OBJ_HASH_KEY);
value = hashTypeCurrentFromHashTable(&hi, OBJ_HASH_VALUE);
newfield = sdsdup(field);
newvalue = sdsdup(value);
/* Add a field-value pair to a new hash object. */
dictAdd(d, newfield, newvalue);
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
hobj = createObject(OBJ_HASH, d);
hobj->encoding = OBJ_ENCODING_HT;
@ -812,7 +809,7 @@ static void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int wh
void genericHgetallCommand(client *c, int flags) {
robj *o;
hashTypeIterator *hi;
hashTypeIterator hi;
int length, count = 0;
robj *emptyResp = (flags & OBJ_HASH_KEY && flags & OBJ_HASH_VALUE) ? shared.emptymap[c->resp] : shared.emptyarray;
@ -827,19 +824,19 @@ void genericHgetallCommand(client *c, int flags) {
addReplyArrayLen(c, length);
}
hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != C_ERR) {
hashTypeInitIterator(o, &hi);
while (hashTypeNext(&hi) != C_ERR) {
if (flags & OBJ_HASH_KEY) {
addHashIteratorCursorToReply(c, hi, OBJ_HASH_KEY);
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_KEY);
count++;
}
if (flags & OBJ_HASH_VALUE) {
addHashIteratorCursorToReply(c, hi, OBJ_HASH_VALUE);
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_VALUE);
count++;
}
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
/* Make sure we returned the right number of elements. */
if (flags & OBJ_HASH_KEY && flags & OBJ_HASH_VALUE) count /= 2;
@ -973,13 +970,14 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
* The number of requested elements is greater than the number of
* elements inside the hash: simply return the whole hash. */
if (count >= size) {
hashTypeIterator *hi = hashTypeInitIterator(hash);
while (hashTypeNext(hi) != C_ERR) {
hashTypeIterator hi;
hashTypeInitIterator(hash, &hi);
while (hashTypeNext(&hi) != C_ERR) {
if (withvalues && c->resp > 2) addReplyArrayLen(c, 2);
addHashIteratorCursorToReply(c, hi, OBJ_HASH_KEY);
if (withvalues) addHashIteratorCursorToReply(c, hi, OBJ_HASH_VALUE);
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_KEY);
if (withvalues) addHashIteratorCursorToReply(c, &hi, OBJ_HASH_VALUE);
}
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
return;
}
@ -1015,21 +1013,22 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
/* Hashtable encoding (generic implementation) */
dict *d = dictCreate(&sdsReplyDictType);
dictExpand(d, size);
hashTypeIterator *hi = hashTypeInitIterator(hash);
hashTypeIterator hi;
hashTypeInitIterator(hash, &hi);
/* Add all the elements into the temporary dictionary. */
while ((hashTypeNext(hi)) != C_ERR) {
while ((hashTypeNext(&hi)) != C_ERR) {
int ret = DICT_ERR;
sds key, value = NULL;
key = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
if (withvalues) value = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
key = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
if (withvalues) value = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
ret = dictAdd(d, key, value);
serverAssert(ret == DICT_OK);
}
serverAssert(dictSize(d) == size);
hashTypeReleaseIterator(hi);
hashTypeResetIterator(&hi);
/* Remove random elements to reach the right count. */
while (size > count) {