Commit e19c5c8c authored by antirez's avatar antirez
Browse files

TCC: use threaded SUNION/DIFF only for large sets.

parent 712db71e
...@@ -1772,7 +1772,9 @@ int lockedClientListMatch(void *a, void *b) { ...@@ -1772,7 +1772,9 @@ int lockedClientListMatch(void *a, void *b) {
* *
* When locking fails C_ERR is returned, otherwise C_OK is returned. * When locking fails C_ERR is returned, otherwise C_OK is returned.
* Note that 'optr' may be populated with NULL if the key that is going * Note that 'optr' may be populated with NULL if the key that is going
* to be locked is empty. * to be locked is empty. If 'optr' is NULL, the object is not returned.
* This is often useful since we lookup the key and already have the object
* and later lock the key if needed (for instance if the value is large).
* *
* Signaling of the need to lock keys is performed using the * Signaling of the need to lock keys is performed using the
* wouldLockKey() API (XXX: yet to be implemented). Check the function * wouldLockKey() API (XXX: yet to be implemented). Check the function
...@@ -1818,7 +1820,7 @@ int lockKey(client *c, robj *key, int locktype, robj **optr) { ...@@ -1818,7 +1820,7 @@ int lockKey(client *c, robj *key, int locktype, robj **optr) {
* that without crashing. So that command implementations don't * that without crashing. So that command implementations don't
* have to do complex checks in the command line in case of repeating * have to do complex checks in the command line in case of repeating
* keys. */ * keys. */
*optr = lk->obj; if (optr) *optr = lk->obj;
return C_OK; return C_OK;
} }
incrRefCount(key); incrRefCount(key);
...@@ -1832,7 +1834,7 @@ int lockKey(client *c, robj *key, int locktype, robj **optr) { ...@@ -1832,7 +1834,7 @@ int lockKey(client *c, robj *key, int locktype, robj **optr) {
* blocked handle, we can still track the original ID even if the * blocked handle, we can still track the original ID even if the
* client is gone. */ * client is gone. */
dictSetUnsignedIntegerVal(de,c->id); dictSetUnsignedIntegerVal(de,c->id);
*optr = lk->obj; if (optr) *optr = lk->obj;
return C_OK; return C_OK;
} }
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include "server.h" #include "server.h"
/* Use threaded execution, when available, if at least one of the sets
* involved is greater or equal to the threshold. */
#define THREADED_SET_SIZE_THRESHOLD 5000
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
* Set Commands * Set Commands
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
...@@ -1093,7 +1097,8 @@ void sunionDiffThreadedHalf(client *c, void *options) { ...@@ -1093,7 +1097,8 @@ void sunionDiffThreadedHalf(client *c, void *options) {
void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum, void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
robj *dstkey, int op, int sync) { robj *dstkey, int op, int sync) {
robj **sets = zmalloc(sizeof(robj*)*setnum); robj **sets = zmalloc(sizeof(robj*)*setnum);
int threaded = (dstkey == NULL && !sync); int threaded_call_allowed = (dstkey == NULL && !sync);
int threaded = 0;
for (int j = 0; j < setnum; j++) { for (int j = 0; j < setnum; j++) {
robj *setobj = dstkey ? robj *setobj = dstkey ?
...@@ -1107,16 +1112,23 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum, ...@@ -1107,16 +1112,23 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
zfree(sets); zfree(sets);
return; return;
} }
sets[j] = setobj;
if (threaded_call_allowed &&
setTypeSize(setobj) >= THREADED_SET_SIZE_THRESHOLD)
{
threaded = 1;
}
}
/* Try to lock the key if this is a threaded execution. If we /* Try to lock the keys only if this is a threaded execution. If we
* fail we just revert to non threaded execution. */ * fail we just revert to non threaded execution. */
if (threaded) { if (threaded) {
if (lockKey(c,setkeys[j],LOCKEDKEY_READ,&setobj) == C_ERR) { for (int j = 0; j < setnum; j++) {
if (lockKey(c,setkeys[j],LOCKEDKEY_READ,NULL) == C_ERR) {
unlockAllKeys(c); unlockAllKeys(c);
threaded = 0; threaded = 0;
} }
} }
sets[j] = setobj;
} }
struct sunionDiffThreadOptions *opt = zmalloc(sizeof(*opt)); struct sunionDiffThreadOptions *opt = zmalloc(sizeof(*opt));
...@@ -1126,8 +1138,6 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum, ...@@ -1126,8 +1138,6 @@ void sunionDiffGenericCommand(client *c, robj **setkeys, int setnum,
opt->dstkey = dstkey; opt->dstkey = dstkey;
opt->threaded = threaded; opt->threaded = threaded;
/* TODO: Execute in threaded mode only if we have at least a
* large set. */
if (threaded) { if (threaded) {
executeThreadedCommand(c,sunionDiffThreadedHalf,opt); executeThreadedCommand(c,sunionDiffThreadedHalf,opt);
} else { } else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment