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)
|
||||
{
|
||||
#define MERGE_BLOCK_SIZE 4
|
||||
dictEntry *rgdeT[MERGE_BLOCK_SIZE];
|
||||
|
||||
assert(dst != src);
|
||||
if (dictSize(src) == 0)
|
||||
return DICT_OK;
|
||||
@ -210,6 +213,50 @@ int dictMerge(dict *dst, dict *src)
|
||||
}
|
||||
_dictReset(&src->ht[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);
|
||||
return DICT_OK;
|
||||
}
|
||||
@ -218,10 +265,34 @@ int dictMerge(dict *dst, dict *src)
|
||||
auto &htDst = dictIsRehashing(dst) ? dst->ht[1] : dst->ht[0];
|
||||
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)
|
||||
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];
|
||||
src->ht[iht].table[ide] = nullptr;
|
||||
while (de != nullptr)
|
||||
@ -236,6 +307,7 @@ int dictMerge(dict *dst, dict *src)
|
||||
de = deNext;
|
||||
src->ht[iht].used--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
assert((dictSize(src)+dictSize(dst)) == expectedSize);
|
||||
|
Loading…
x
Reference in New Issue
Block a user