Skip to content

Commit

Permalink
QHash: Return void from QHashPrivate::Data::erase()
Browse files Browse the repository at this point in the history
This removes some calculations that are not required in
80% of the cases where d->erase() is being called (as
the return value is ignored). When removing lots of
elements from the hash, the ++it could loop quite a
bit until it found the next valid item in the hash.

This chain of changes combined improve the overall performance of
QHash by 10-50% depending on the operation. Deletes are twice
as fast, reads around 20% faster, inserts around 10% faster.

Task-number: QTBUG-91739
Fixes: QTBUG-98436
Change-Id: I2d82a7c9dd1dd0a4da8402e6d95bfd620caeff3a
Reviewed-by: Marc Mutz <[email protected]>
  • Loading branch information
laknoll authored and Morten242 committed Dec 17, 2021
1 parent 46dc8e4 commit 1cc5948
Showing 1 changed file with 11 additions and 9 deletions.
20 changes: 11 additions & 9 deletions src/corelib/tools/qhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,21 +746,19 @@ struct Data
return { it.toIterator(this), false };
}

iterator erase(Bucket bucket) noexcept(std::is_nothrow_destructible<Node>::value)
void erase(Bucket bucket) noexcept(std::is_nothrow_destructible<Node>::value)
{
Q_ASSERT(bucket.span->hasNode(bucket.index));
bucket.span->erase(bucket.index);
--size;

Bucket originalBucket = bucket;

// re-insert the following entries to avoid holes
Bucket next = bucket;
while (true) {
next.advanceWrapped(this);
size_t offset = next.offset();
if (offset == SpanConstants::UnusedEntry)
break;
return;
size_t hash = QHashPrivate::calculateHash(next.nodeAtOffset(offset).key, seed);
Bucket newBucket(this, GrowthPolicy::bucketForHash(numBuckets, hash));
while (true) {
Expand All @@ -781,9 +779,6 @@ struct Data
newBucket.advanceWrapped(this);
}
}
if (originalBucket.toBucketIndex(this) == numBuckets - 1 || originalBucket.isUnused())
return ++(originalBucket.toIterator(this));
return originalBucket.toIterator(this);
}

~Data()
Expand Down Expand Up @@ -1242,7 +1237,10 @@ class QHash
iterator i = iterator{d->detachedIterator(it.i)};
typename Data::Bucket bucket(i.i);

return iterator(d->erase(bucket));
d->erase(bucket);
if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
++i;
return i;
}

QPair<iterator, iterator> equal_range(const Key &key)
Expand Down Expand Up @@ -1880,7 +1878,11 @@ class QMultiHash
if (i.e == &i.i.node()->value) {
// last remaining entry, erase
typename Data::Bucket bucket(i.i);
i = iterator(d->erase(bucket));
d->erase(bucket);
if (bucket.toBucketIndex(d) == d->numBuckets - 1 || bucket.isUnused())
i = iterator(++iter.i);
else // 'i' currently has a nullptr chain. So, we must recreate it
i = iterator(bucket.toIterator(d));
} else {
i = iterator(++iter.i);
}
Expand Down

0 comments on commit 1cc5948

Please sign in to comment.