Skip to content

Commit b5eb793

Browse files
imasahirozuiderkwastMasahiro Ide
authored
Eliminate hashTypeIterator memory allocation by assigning it on stack (#1105)
Signed-off-by: Masahiro Ide <[email protected]> Signed-off-by: Masahiro Ide <[email protected]> Co-authored-by: Viktor Söderqvist <[email protected]> Co-authored-by: Masahiro Ide <[email protected]>
1 parent a1cc7c2 commit b5eb793

File tree

4 files changed

+53
-53
lines changed

4 files changed

+53
-53
lines changed

src/aof.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -1947,30 +1947,30 @@ static int rioWriteHashIteratorCursor(rio *r, hashTypeIterator *hi, int what) {
19471947
/* Emit the commands needed to rebuild a hash object.
19481948
* The function returns 0 on error, 1 on success. */
19491949
int rewriteHashObject(rio *r, robj *key, robj *o) {
1950-
hashTypeIterator *hi;
1950+
hashTypeIterator hi;
19511951
long long count = 0, items = hashTypeLength(o);
19521952

1953-
hi = hashTypeInitIterator(o);
1954-
while (hashTypeNext(hi) != C_ERR) {
1953+
hashTypeInitIterator(o, &hi);
1954+
while (hashTypeNext(&hi) != C_ERR) {
19551955
if (count == 0) {
19561956
int cmd_items = (items > AOF_REWRITE_ITEMS_PER_CMD) ? AOF_REWRITE_ITEMS_PER_CMD : items;
19571957

19581958
if (!rioWriteBulkCount(r, '*', 2 + cmd_items * 2) || !rioWriteBulkString(r, "HMSET", 5) ||
19591959
!rioWriteBulkObject(r, key)) {
1960-
hashTypeReleaseIterator(hi);
1960+
hashTypeResetIterator(&hi);
19611961
return 0;
19621962
}
19631963
}
19641964

1965-
if (!rioWriteHashIteratorCursor(r, hi, OBJ_HASH_KEY) || !rioWriteHashIteratorCursor(r, hi, OBJ_HASH_VALUE)) {
1966-
hashTypeReleaseIterator(hi);
1965+
if (!rioWriteHashIteratorCursor(r, &hi, OBJ_HASH_KEY) || !rioWriteHashIteratorCursor(r, &hi, OBJ_HASH_VALUE)) {
1966+
hashTypeResetIterator(&hi);
19671967
return 0;
19681968
}
19691969
if (++count == AOF_REWRITE_ITEMS_PER_CMD) count = 0;
19701970
items--;
19711971
}
19721972

1973-
hashTypeReleaseIterator(hi);
1973+
hashTypeResetIterator(&hi);
19741974

19751975
return 1;
19761976
}

src/debug.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -221,21 +221,22 @@ void xorObjectDigest(serverDb *db, robj *keyobj, unsigned char *digest, robj *o)
221221
serverPanic("Unknown sorted set encoding");
222222
}
223223
} else if (o->type == OBJ_HASH) {
224-
hashTypeIterator *hi = hashTypeInitIterator(o);
225-
while (hashTypeNext(hi) != C_ERR) {
224+
hashTypeIterator hi;
225+
hashTypeInitIterator(o, &hi);
226+
while (hashTypeNext(&hi) != C_ERR) {
226227
unsigned char eledigest[20];
227228
sds sdsele;
228229

229230
memset(eledigest, 0, 20);
230-
sdsele = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
231+
sdsele = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
231232
mixDigest(eledigest, sdsele, sdslen(sdsele));
232233
sdsfree(sdsele);
233-
sdsele = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
234+
sdsele = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
234235
mixDigest(eledigest, sdsele, sdslen(sdsele));
235236
sdsfree(sdsele);
236237
xorDigest(digest, eledigest, 20);
237238
}
238-
hashTypeReleaseIterator(hi);
239+
hashTypeResetIterator(&hi);
239240
} else if (o->type == OBJ_STREAM) {
240241
streamIterator si;
241242
streamIteratorStart(&si, o->ptr, NULL, NULL, 0);

src/server.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -2603,7 +2603,7 @@ typedef struct {
26032603

26042604
unsigned char *fptr, *vptr;
26052605

2606-
dictIterator *di;
2606+
dictIterator di;
26072607
dictEntry *de;
26082608
} hashTypeIterator;
26092609

@@ -3370,8 +3370,8 @@ void hashTypeTryConversion(robj *subject, robj **argv, int start, int end);
33703370
int hashTypeExists(robj *o, sds key);
33713371
int hashTypeDelete(robj *o, sds key);
33723372
unsigned long hashTypeLength(const robj *o);
3373-
hashTypeIterator *hashTypeInitIterator(robj *subject);
3374-
void hashTypeReleaseIterator(hashTypeIterator *hi);
3373+
void hashTypeInitIterator(robj *subject, hashTypeIterator *hi);
3374+
void hashTypeResetIterator(hashTypeIterator *hi);
33753375
int hashTypeNext(hashTypeIterator *hi);
33763376
void hashTypeCurrentFromListpack(hashTypeIterator *hi,
33773377
int what,

src/t_hash.c

+37-38
Original file line numberDiff line numberDiff line change
@@ -307,25 +307,22 @@ unsigned long hashTypeLength(const robj *o) {
307307
return length;
308308
}
309309

310-
hashTypeIterator *hashTypeInitIterator(robj *subject) {
311-
hashTypeIterator *hi = zmalloc(sizeof(hashTypeIterator));
310+
void hashTypeInitIterator(robj *subject, hashTypeIterator *hi) {
312311
hi->subject = subject;
313312
hi->encoding = subject->encoding;
314313

315314
if (hi->encoding == OBJ_ENCODING_LISTPACK) {
316315
hi->fptr = NULL;
317316
hi->vptr = NULL;
318317
} else if (hi->encoding == OBJ_ENCODING_HT) {
319-
hi->di = dictGetIterator(subject->ptr);
318+
dictInitIterator(&hi->di, subject->ptr);
320319
} else {
321320
serverPanic("Unknown hash encoding");
322321
}
323-
return hi;
324322
}
325323

326-
void hashTypeReleaseIterator(hashTypeIterator *hi) {
327-
if (hi->encoding == OBJ_ENCODING_HT) dictReleaseIterator(hi->di);
328-
zfree(hi);
324+
void hashTypeResetIterator(hashTypeIterator *hi) {
325+
if (hi->encoding == OBJ_ENCODING_HT) dictResetIterator(&hi->di);
329326
}
330327

331328
/* Move to the next entry in the hash. Return C_OK when the next entry
@@ -358,7 +355,7 @@ int hashTypeNext(hashTypeIterator *hi) {
358355
hi->fptr = fptr;
359356
hi->vptr = vptr;
360357
} else if (hi->encoding == OBJ_ENCODING_HT) {
361-
if ((hi->de = dictNext(hi->di)) == NULL) return C_ERR;
358+
if ((hi->de = dictNext(&hi->di)) == NULL) return C_ERR;
362359
} else {
363360
serverPanic("Unknown hash encoding");
364361
}
@@ -448,31 +445,31 @@ void hashTypeConvertListpack(robj *o, int enc) {
448445
/* Nothing to do... */
449446

450447
} else if (enc == OBJ_ENCODING_HT) {
451-
hashTypeIterator *hi;
448+
hashTypeIterator hi;
452449
dict *dict;
453450
int ret;
454451

455-
hi = hashTypeInitIterator(o);
452+
hashTypeInitIterator(o, &hi);
456453
dict = dictCreate(&hashDictType);
457454

458455
/* Presize the dict to avoid rehashing */
459456
dictExpand(dict, hashTypeLength(o));
460457

461-
while (hashTypeNext(hi) != C_ERR) {
458+
while (hashTypeNext(&hi) != C_ERR) {
462459
sds key, value;
463460

464-
key = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
465-
value = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
461+
key = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
462+
value = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
466463
ret = dictAdd(dict, key, value);
467464
if (ret != DICT_OK) {
468465
sdsfree(key);
469-
sdsfree(value); /* Needed for gcc ASAN */
470-
hashTypeReleaseIterator(hi); /* Needed for gcc ASAN */
466+
sdsfree(value); /* Needed for gcc ASAN */
467+
hashTypeResetIterator(&hi); /* Needed for gcc ASAN */
471468
serverLogHexDump(LL_WARNING, "listpack with dup elements dump", o->ptr, lpBytes(o->ptr));
472469
serverPanic("Listpack corruption detected");
473470
}
474471
}
475-
hashTypeReleaseIterator(hi);
472+
hashTypeResetIterator(&hi);
476473
zfree(o->ptr);
477474
o->encoding = OBJ_ENCODING_HT;
478475
o->ptr = dict;
@@ -498,7 +495,7 @@ void hashTypeConvert(robj *o, int enc) {
498495
* The resulting object always has refcount set to 1 */
499496
robj *hashTypeDup(robj *o) {
500497
robj *hobj;
501-
hashTypeIterator *hi;
498+
hashTypeIterator hi;
502499

503500
serverAssert(o->type == OBJ_HASH);
504501

@@ -513,20 +510,20 @@ robj *hashTypeDup(robj *o) {
513510
dict *d = dictCreate(&hashDictType);
514511
dictExpand(d, dictSize((const dict *)o->ptr));
515512

516-
hi = hashTypeInitIterator(o);
517-
while (hashTypeNext(hi) != C_ERR) {
513+
hashTypeInitIterator(o, &hi);
514+
while (hashTypeNext(&hi) != C_ERR) {
518515
sds field, value;
519516
sds newfield, newvalue;
520517
/* Extract a field-value pair from an original hash object.*/
521-
field = hashTypeCurrentFromHashTable(hi, OBJ_HASH_KEY);
522-
value = hashTypeCurrentFromHashTable(hi, OBJ_HASH_VALUE);
518+
field = hashTypeCurrentFromHashTable(&hi, OBJ_HASH_KEY);
519+
value = hashTypeCurrentFromHashTable(&hi, OBJ_HASH_VALUE);
523520
newfield = sdsdup(field);
524521
newvalue = sdsdup(value);
525522

526523
/* Add a field-value pair to a new hash object. */
527524
dictAdd(d, newfield, newvalue);
528525
}
529-
hashTypeReleaseIterator(hi);
526+
hashTypeResetIterator(&hi);
530527

531528
hobj = createObject(OBJ_HASH, d);
532529
hobj->encoding = OBJ_ENCODING_HT;
@@ -812,7 +809,7 @@ static void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int wh
812809

813810
void genericHgetallCommand(client *c, int flags) {
814811
robj *o;
815-
hashTypeIterator *hi;
812+
hashTypeIterator hi;
816813
int length, count = 0;
817814

818815
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) {
827824
addReplyArrayLen(c, length);
828825
}
829826

830-
hi = hashTypeInitIterator(o);
831-
while (hashTypeNext(hi) != C_ERR) {
827+
hashTypeInitIterator(o, &hi);
828+
while (hashTypeNext(&hi) != C_ERR) {
832829
if (flags & OBJ_HASH_KEY) {
833-
addHashIteratorCursorToReply(c, hi, OBJ_HASH_KEY);
830+
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_KEY);
834831
count++;
835832
}
836833
if (flags & OBJ_HASH_VALUE) {
837-
addHashIteratorCursorToReply(c, hi, OBJ_HASH_VALUE);
834+
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_VALUE);
838835
count++;
839836
}
840837
}
841838

842-
hashTypeReleaseIterator(hi);
839+
hashTypeResetIterator(&hi);
843840

844841
/* Make sure we returned the right number of elements. */
845842
if (flags & OBJ_HASH_KEY && flags & OBJ_HASH_VALUE) count /= 2;
@@ -973,13 +970,14 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
973970
* The number of requested elements is greater than the number of
974971
* elements inside the hash: simply return the whole hash. */
975972
if (count >= size) {
976-
hashTypeIterator *hi = hashTypeInitIterator(hash);
977-
while (hashTypeNext(hi) != C_ERR) {
973+
hashTypeIterator hi;
974+
hashTypeInitIterator(hash, &hi);
975+
while (hashTypeNext(&hi) != C_ERR) {
978976
if (withvalues && c->resp > 2) addReplyArrayLen(c, 2);
979-
addHashIteratorCursorToReply(c, hi, OBJ_HASH_KEY);
980-
if (withvalues) addHashIteratorCursorToReply(c, hi, OBJ_HASH_VALUE);
977+
addHashIteratorCursorToReply(c, &hi, OBJ_HASH_KEY);
978+
if (withvalues) addHashIteratorCursorToReply(c, &hi, OBJ_HASH_VALUE);
981979
}
982-
hashTypeReleaseIterator(hi);
980+
hashTypeResetIterator(&hi);
983981
return;
984982
}
985983

@@ -1015,21 +1013,22 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
10151013
/* Hashtable encoding (generic implementation) */
10161014
dict *d = dictCreate(&sdsReplyDictType);
10171015
dictExpand(d, size);
1018-
hashTypeIterator *hi = hashTypeInitIterator(hash);
1016+
hashTypeIterator hi;
1017+
hashTypeInitIterator(hash, &hi);
10191018

10201019
/* Add all the elements into the temporary dictionary. */
1021-
while ((hashTypeNext(hi)) != C_ERR) {
1020+
while ((hashTypeNext(&hi)) != C_ERR) {
10221021
int ret = DICT_ERR;
10231022
sds key, value = NULL;
10241023

1025-
key = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_KEY);
1026-
if (withvalues) value = hashTypeCurrentObjectNewSds(hi, OBJ_HASH_VALUE);
1024+
key = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_KEY);
1025+
if (withvalues) value = hashTypeCurrentObjectNewSds(&hi, OBJ_HASH_VALUE);
10271026
ret = dictAdd(d, key, value);
10281027

10291028
serverAssert(ret == DICT_OK);
10301029
}
10311030
serverAssert(dictSize(d) == size);
1032-
hashTypeReleaseIterator(hi);
1031+
hashTypeResetIterator(&hi);
10331032

10341033
/* Remove random elements to reach the right count. */
10351034
while (size > count) {

0 commit comments

Comments
 (0)