Skip to content

Commit 89e5298

Browse files
committed
Execute MGET and MSET in batches
Signed-off-by: Viktor Söderqvist <[email protected]>
1 parent 0ce0c4b commit 89e5298

File tree

3 files changed

+18
-8
lines changed

3 files changed

+18
-8
lines changed

src/memory_prefetch.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,13 @@ void removeClientFromPendingCommandsBatch(client *c) {
282282

283283
/* A simple way to prefetch the keys for a client command execution. This can be
284284
* used for optimizing multi-key commands like mget, mset, etc. */
285-
void prefetchKeys(client *c, int first, int step) {
285+
void prefetchKeys(client *c, int first, int step, int count) {
286286
/* Skip this for IO threads. Keys are already batch-prefetched. */
287287
if (c->io_parsed_cmd) return;
288288

289289
int n = (c->argc - first) / step;
290-
if (n < 2) return; /* There's no benefit in prefetcing only one key. */
291-
if (n > 32) n = 32; /* Prefetching too many keys doesn't help the cache. */
290+
if (count < n) n = count;
291+
if (n < 2) return; /* There's no benefit in prefetcing only one key. */
292292
hashtableIncrementalFindState states[n];
293293
int i, arg;
294294
for (i = 0, arg = first; i < n && arg < c->argc; i++, arg += step) {

src/memory_prefetch.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ void processClientsCommandsBatch(void);
88
int addCommandToBatchAndProcessIfFull(struct client *c);
99
void removeClientFromPendingCommandsBatch(struct client *c);
1010

11-
void prefetchKeys(struct client *c, int first, int step);
11+
void prefetchKeys(struct client *c, int first, int step, int count);
1212

1313
#endif /* MEMORY_PREFETCH_H */

src/t_string.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,14 @@ void getrangeCommand(client *c) {
606606
}
607607

608608
void mgetCommand(client *c) {
609+
const int batch_size = 16;
609610
int j;
610-
prefetchKeys(c, 1, 1);
611611
addReplyArrayLen(c, c->argc - 1);
612612
for (j = 1; j < c->argc; j++) {
613+
if (j % batch_size == 1) {
614+
/* Prefetch the next batch of keys */
615+
prefetchKeys(c, j, 1, batch_size);
616+
}
613617
robj *o = lookupKeyRead(c->db, c->argv[j]);
614618
if (o == NULL) {
615619
addReplyNull(c);
@@ -624,20 +628,22 @@ void mgetCommand(client *c) {
624628
}
625629

626630
void msetGenericCommand(client *c, int nx) {
631+
const int batch_size = 16;
627632
int j;
628633

629634
if ((c->argc % 2) == 0) {
630635
addReplyErrorArity(c);
631636
return;
632637
}
633638

634-
/* Prefetch the keys from memory in parallel. */
635-
prefetchKeys(c, 1, 2);
636-
637639
/* Handle the NX flag. The MSETNX semantic is to return zero and don't
638640
* set anything if at least one key already exists. */
639641
if (nx) {
640642
for (j = 1; j < c->argc; j += 2) {
643+
if (j % (batch_size * 2) == 1) {
644+
/* Prefetch the next batch of keys */
645+
prefetchKeys(c, j, 2, batch_size);
646+
}
641647
if (lookupKeyWrite(c->db, c->argv[j]) != NULL) {
642648
addReply(c, shared.czero);
643649
return;
@@ -647,6 +653,10 @@ void msetGenericCommand(client *c, int nx) {
647653

648654
int setkey_flags = nx ? SETKEY_DOESNT_EXIST : 0;
649655
for (j = 1; j < c->argc; j += 2) {
656+
if (!nx && j % (batch_size * 2) == 1) {
657+
/* Prefetch the next batch of keys */
658+
prefetchKeys(c, j, 2, batch_size);
659+
}
650660
robj *val = tryObjectEncoding(c->argv[j + 1]);
651661
setKey(c, c->db, c->argv[j], &val, setkey_flags);
652662
incrRefCount(val);

0 commit comments

Comments
 (0)