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

View File

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

View File

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

View File

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