summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qlist.h
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2020-10-27 20:00:18 +0100
committerLars Knoll <lars.knoll@qt.io>2020-11-04 11:21:59 +0100
commit8f7016252a846e30efb617d2e20e929579772456 (patch)
treefb6f5506dcf180915f70a124f4631dd07a88b94c /src/corelib/tools/qlist.h
parent4deb0d1737284e24e15ef153aa0d18daea5f731d (diff)
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>
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r--src/corelib/tools/qlist.h22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index da3a5926ea..f3e78b4cdb 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -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)
{