From 8f7016252a846e30efb617d2e20e929579772456 Mon Sep 17 00:00:00 2001 From: Andrei Golubev Date: Tue, 27 Oct 2020 20:00:18 +0100 Subject: Implement QList::emplaceBack as a proper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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 Reviewed-by: MÃ¥rten Nordheim --- src/corelib/tools/qlist.h | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/corelib/tools/qlist.h') 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 &l) @@ -324,8 +323,8 @@ public: void prepend(rvalue_ref t) { emplaceFront(std::move(t)); } void prepend(parameter_type t) { emplaceFront(t); } - template - reference emplaceBack(Args&&... args) { return *emplace(count(), std::forward(args)...); } + template + inline reference emplaceBack(Args &&... args); template inline reference emplaceFront(Args&&... args); @@ -766,6 +765,21 @@ QList::emplace(qsizetype i, Args&&... args) return d.begin() + i; } +template +template +inline typename QList::reference QList::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)...); + d.swap(detached); + } else { + d->emplace(d.end(), std::forward(args)...); + } + return *(d.end() - 1); +} + template typename QList::iterator QList::erase(const_iterator abegin, const_iterator aend) { -- cgit v1.2.3