dictMerge perf improvements

Former-commit-id: 48401ec369c5693689ef658cca518dc94ab1402e
This commit is contained in:
John Sully 2020-08-15 23:14:29 +00:00
parent eb572c57e2
commit 1055543817

View File

@ -179,6 +179,9 @@ int dictExpand(dict *d, unsigned long size)
int dictMerge(dict *dst, dict *src) int dictMerge(dict *dst, dict *src)
{ {
#define MERGE_BLOCK_SIZE 4
dictEntry *rgdeT[MERGE_BLOCK_SIZE];
assert(dst != src); assert(dst != src);
if (dictSize(src) == 0) if (dictSize(src) == 0)
return DICT_OK; return DICT_OK;
@ -210,6 +213,50 @@ int dictMerge(dict *dst, dict *src)
} }
_dictReset(&src->ht[0]); _dictReset(&src->ht[0]);
dst->rehashidx = 0; dst->rehashidx = 0;
assert(dictIsRehashing(dst));
assert((dictSize(src)+dictSize(dst)) == expectedSize);
return DICT_OK;
}
if (!dictIsRehashing(src) && dictSize(src) > 0 &&
(src->ht[0].size == dst->ht[0].size || src->ht[0].size == dst->ht[1].size))
{
auto &htDst = (src->ht[0].size == dst->ht[0].size) ? dst->ht[0] : dst->ht[1];
assert(src->ht[0].size == htDst.size);
for (size_t ide = 0; ide < src->ht[0].size; ide += MERGE_BLOCK_SIZE)
{
if (src->ht[0].used == 0)
break;
for (int dde = 0; dde < MERGE_BLOCK_SIZE; ++dde) {
rgdeT[dde] = src->ht[0].table[ide + dde];
src->ht[0].table[ide + dde] = nullptr;
}
for (;;) {
bool fAnyFound = false;
for (int dde = 0; dde < MERGE_BLOCK_SIZE; ++dde) {
if (rgdeT[dde] == nullptr)
continue;
dictEntry *deNext = rgdeT[dde]->next;
rgdeT[dde]->next = htDst.table[ide+dde];
htDst.table[ide+dde] = rgdeT[dde];
rgdeT[dde] = deNext;
htDst.used++;
src->ht[0].used--;
fAnyFound = fAnyFound || (deNext != nullptr);
}
if (!fAnyFound)
break;
}
}
// If we copied to the base hash table of a rehashing dst, reset the rehash
if (dictIsRehashing(dst) && src->ht[0].size == dst->ht[0].size)
dst->rehashidx = 0;
assert(dictSize(src) == 0);
assert((dictSize(src)+dictSize(dst)) == expectedSize); assert((dictSize(src)+dictSize(dst)) == expectedSize);
return DICT_OK; return DICT_OK;
} }
@ -218,10 +265,34 @@ int dictMerge(dict *dst, dict *src)
auto &htDst = dictIsRehashing(dst) ? dst->ht[1] : dst->ht[0]; auto &htDst = dictIsRehashing(dst) ? dst->ht[1] : dst->ht[0];
for (int iht = 0; iht < 2; ++iht) for (int iht = 0; iht < 2; ++iht)
{ {
for (size_t ide = 0; ide < src->ht[iht].size; ++ide) for (size_t ide = 0; ide < src->ht[iht].size; ide += MERGE_BLOCK_SIZE)
{ {
if (src->ht[iht].used == 0) if (src->ht[iht].used == 0)
break; break;
for (int dde = 0; dde < MERGE_BLOCK_SIZE; ++dde) {
rgdeT[dde] = src->ht[iht].table[ide + dde];
src->ht[iht].table[ide + dde] = nullptr;
}
for (;;) {
bool fAnyFound = false;
for (int dde = 0; dde < MERGE_BLOCK_SIZE; ++dde) {
if (rgdeT[dde] == nullptr)
continue;
uint64_t h = dictHashKey(dst, rgdeT[dde]->key) & htDst.sizemask;
dictEntry *deNext = rgdeT[dde]->next;
rgdeT[dde]->next = htDst.table[h];
htDst.table[h] = rgdeT[dde];
rgdeT[dde] = deNext;
htDst.used++;
src->ht[iht].used--;
fAnyFound = fAnyFound || (deNext != nullptr);
}
if (!fAnyFound)
break;
}
#if 0
dictEntry *de = src->ht[iht].table[ide]; dictEntry *de = src->ht[iht].table[ide];
src->ht[iht].table[ide] = nullptr; src->ht[iht].table[ide] = nullptr;
while (de != nullptr) while (de != nullptr)
@ -236,6 +307,7 @@ int dictMerge(dict *dst, dict *src)
de = deNext; de = deNext;
src->ht[iht].used--; src->ht[iht].used--;
} }
#endif
} }
} }
assert((dictSize(src)+dictSize(dst)) == expectedSize); assert((dictSize(src)+dictSize(dst)) == expectedSize);