1
0
mirror of https://github.com/fluencelabs/redis synced 2025-03-18 00:20:50 +00:00

Less blocking dictGetRandomKeys().

Related to issue .
This commit is contained in:
antirez 2015-02-04 22:12:46 +01:00
parent 5e3dcc522b
commit 170e41464d

@ -666,34 +666,42 @@ dictEntry *dictGetRandomKey(dict *d)
* at producing N elements, and the elements are guaranteed to be non * at producing N elements, and the elements are guaranteed to be non
* repeating. */ * repeating. */
unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) { unsigned int dictGetRandomKeys(dict *d, dictEntry **des, unsigned int count) {
int j; /* internal hash table id, 0 or 1. */ unsigned int j; /* internal hash table id, 0 or 1. */
unsigned int stored = 0; unsigned int tables; /* 1 or 2 tables? */
unsigned int stored = 0, maxsizemask;
if (dictSize(d) < count) count = dictSize(d); if (dictSize(d) < count) count = dictSize(d);
while(stored < count) {
for (j = 0; j < 2; j++) {
/* Pick a random point inside the hash table 0 or 1. */
unsigned int i = random() & d->ht[j].sizemask;
int size = d->ht[j].size;
/* Make sure to visit every bucket by iterating 'size' times. */ /* Try to do a rehashing work proportional to 'count'. */
while(size--) { for (j = 0; j < count; j++) {
dictEntry *he = d->ht[j].table[i]; if (dictIsRehashing(d))
while (he) { _dictRehashStep(d);
/* Collect all the elements of the buckets found non else
* empty while iterating. */ break;
*des = he; }
des++;
he = he->next; tables = dictIsRehashing(d) ? 2 : 1;
stored++; maxsizemask = d->ht[0].sizemask;
if (stored == count) return stored; if (tables > 1 && maxsizemask < d->ht[1].sizemask)
} maxsizemask = d->ht[1].sizemask;
i = (i+1) & d->ht[j].sizemask;
/* Pick a random point inside the larger table. */
unsigned int i = random() & maxsizemask;
while(stored < count) {
for (j = 0; j < tables; j++) {
if (i >= d->ht[j].size) continue; /* Out of range for this table. */
dictEntry *he = d->ht[j].table[i];
while (he) {
/* Collect all the elements of the buckets found non
* empty while iterating. */
*des = he;
des++;
he = he->next;
stored++;
if (stored == count) return stored;
} }
/* If there is only one table and we iterated it all, we should
* already have 'count' elements. Assert this condition. */
assert(dictIsRehashing(d) != 0);
} }
i = (i+1) & maxsizemask;
} }
return stored; /* Never reached. */ return stored; /* Never reached. */
} }