summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-03-15 08:39:51 +0100
committerMÃ¥rten Nordheim <marten.nordheim@qt.io>2021-12-17 20:21:28 +0100
commit1cc5948839edfc4b97013e4c4a9fc390add6151d (patch)
treecce4997742c82cb0ba4492f91ecf437c71198745 /src
parent46dc8e453ae1d0c1eb749cfebe686995f3a6cfd0 (diff)
QHash: Return void from QHashPrivate::Data::erase()
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 <marc.mutz@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qhash.h20
1 files changed, 11 insertions, 9 deletions
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 1ad28b6d23..c4b4098c0f 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -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) {
@@ -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()
@@ -1242,7 +1237,10 @@ public:
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)
@@ -1880,7 +1878,11 @@ public:
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);
}