Implement QList::emplaceBack as a proper function
My endeavours figuring out why QList::append(elem) gives worst performance compared to 5.15 ended up into this commit. After some straightforward fixes, what was left is "everything is uniformly worse" and takes more CPU cycles Introduce emplaceBack implementation as append is quite a special case that could be greatly simplified. This is a "straightforward" part of the optimizations While at it, change append(t) to use emplaceBack(t) For workloads like: QList<int> list; forever { list.append(0); } this gives huge improvement (roughly 30% for 10k+ elements), movable and complex types also get a tiny speedup Task-number: QTBUG-87330 Change-Id: I9261084e545c24e5473234220d2a3f2cd26c2b7f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
4deb0d1737
commit
8f7016252a
@ -310,8 +310,7 @@ public:
|
||||
return data()[i];
|
||||
}
|
||||
const_reference operator[](qsizetype i) const noexcept { return at(i); }
|
||||
void append(parameter_type t)
|
||||
{ append(const_iterator(std::addressof(t)), const_iterator(std::addressof(t)) + 1); }
|
||||
void append(parameter_type t) { emplaceBack(t); }
|
||||
void append(const_iterator i1, const_iterator i2);
|
||||
void append(rvalue_ref t) { emplaceBack(std::move(t)); }
|
||||
void append(const QList<T> &l)
|
||||
@ -324,8 +323,8 @@ public:
|
||||
void prepend(rvalue_ref t) { emplaceFront(std::move(t)); }
|
||||
void prepend(parameter_type t) { emplaceFront(t); }
|
||||
|
||||
template <typename ...Args>
|
||||
reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline reference emplaceBack(Args &&... args);
|
||||
|
||||
template <typename ...Args>
|
||||
inline reference emplaceFront(Args&&... args);
|
||||
@ -766,6 +765,21 @@ QList<T>::emplace(qsizetype i, Args&&... args)
|
||||
return d.begin() + i;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
inline typename QList<T>::reference QList<T>::emplaceBack(Args &&... args)
|
||||
{
|
||||
if (d->needsDetach() || !d.freeSpaceAtEnd()) {
|
||||
DataPointer detached(DataPointer::allocateGrow(d, 1, QArrayData::AllocateAtEnd));
|
||||
detached->copyAppend(constBegin(), constEnd());
|
||||
detached->emplace(detached.end(), std::forward<Args>(args)...);
|
||||
d.swap(detached);
|
||||
} else {
|
||||
d->emplace(d.end(), std::forward<Args>(args)...);
|
||||
}
|
||||
return *(d.end() - 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename QList<T>::iterator QList<T>::erase(const_iterator abegin, const_iterator aend)
|
||||
{
|
||||
|
@ -875,7 +875,7 @@ void tst_QList::appendList() const
|
||||
v6 << (QList<ConstructionCounted>() << 3 << 4);
|
||||
QCOMPARE(v6, expectedFour);
|
||||
QCOMPARE(v6.at(0).copies, 2);
|
||||
QCOMPARE(v6.at(0).moves, 2);
|
||||
QCOMPARE(v6.at(0).moves, 1);
|
||||
|
||||
// +=
|
||||
QList<ConstructionCounted> v7;
|
||||
|
Loading…
Reference in New Issue
Block a user