dictMerge perf improvements
Former-commit-id: 48401ec369c5693689ef658cca518dc94ab1402e
This commit is contained in:
parent
eb572c57e2
commit
1055543817
74
src/dict.cpp
74
src/dict.cpp
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user