QVersionNumber: de-inline QList constructor calls and resize()

The QList<int> range ctor and other QList<int> methods have percolated
up near the top of the list of Clang -ftime-trace most expensive
template instantiations in PCH libQt6Gui.so builds:

**** Templates that took longest to instantiate:
  [...]
  5138 ms: QList<int>::QList<const int *, true> (256 times, avg 20 ms)
  4327 ms: QtPrivate::QCommonArrayOps<int>::appendIteratorRange<const int *> (256 times, avg 16 ms)

The code in 6.3 is already sufficiently different for this patch to
not be applicable there.

Task-number: QTBUG-97601
Change-Id: I4420c8c90e472ecfd679b414cc4334d2ab55cce3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2022-01-18 22:02:20 +01:00
parent 949b85a721
commit b9c55b5b9e
2 changed files with 36 additions and 12 deletions

View File

@ -481,6 +481,29 @@ QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suff
return string.visit([=] (auto string) { return from_string(string, suffixIndex); }); return string.visit([=] (auto string) { return from_string(string, suffixIndex); });
} }
void QVersionNumber::SegmentStorage::setListData(const QList<int> &seg)
{
pointer_segments = new QList<int>(seg);
}
void QVersionNumber::SegmentStorage::setListData(QList<int> &&seg)
{
pointer_segments = new QList<int>(std::move(seg));
}
void QVersionNumber::SegmentStorage::setListData(const int *first, const int *last)
{
pointer_segments = new QList<int>(first, last);
}
void QVersionNumber::SegmentStorage::resize(qsizetype len)
{
if (isUsingPointer())
pointer_segments->resize(len);
else
setInlineSize(len);
}
void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic) void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic)
{ {
pointer_segments = new QList<int>; pointer_segments = new QList<int>;

View File

@ -96,13 +96,15 @@ class QVersionNumber
if (dataFitsInline(seg.data(), seg.size())) if (dataFitsInline(seg.data(), seg.size()))
setInlineData(seg.data(), seg.size()); setInlineData(seg.data(), seg.size());
else else
pointer_segments = new QList<int>(seg); setListData(seg);
} }
Q_CORE_EXPORT void setListData(const QList<int> &seg);
SegmentStorage(const SegmentStorage &other) SegmentStorage(const SegmentStorage &other)
{ {
if (other.isUsingPointer()) if (other.isUsingPointer())
pointer_segments = new QList<int>(*other.pointer_segments); setListData(*other.pointer_segments);
else else
dummy = other.dummy; dummy = other.dummy;
} }
@ -112,7 +114,7 @@ class QVersionNumber
if (isUsingPointer() && other.isUsingPointer()) { if (isUsingPointer() && other.isUsingPointer()) {
*pointer_segments = *other.pointer_segments; *pointer_segments = *other.pointer_segments;
} else if (other.isUsingPointer()) { } else if (other.isUsingPointer()) {
pointer_segments = new QList<int>(*other.pointer_segments); setListData(*other.pointer_segments);
} else { } else {
if (isUsingPointer()) if (isUsingPointer())
delete pointer_segments; delete pointer_segments;
@ -139,8 +141,11 @@ class QVersionNumber
if (dataFitsInline(std::as_const(seg).data(), seg.size())) if (dataFitsInline(std::as_const(seg).data(), seg.size()))
setInlineData(std::as_const(seg).data(), seg.size()); setInlineData(std::as_const(seg).data(), seg.size());
else else
pointer_segments = new QList<int>(std::move(seg)); setListData(std::move(seg));
} }
Q_CORE_EXPORT void setListData(QList<int> &&seg);
explicit SegmentStorage(std::initializer_list<int> args) explicit SegmentStorage(std::initializer_list<int> args)
: SegmentStorage(args.begin(), args.end()) {} : SegmentStorage(args.begin(), args.end()) {}
@ -149,10 +154,12 @@ class QVersionNumber
if (dataFitsInline(first, last - first)) { if (dataFitsInline(first, last - first)) {
setInlineData(first, last - first); setInlineData(first, last - first);
} else { } else {
pointer_segments = new QList<int>(first, last); setListData(first, last);
} }
} }
Q_CORE_EXPORT void setListData(const int *first, const int *last);
~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; }
bool isUsingPointer() const noexcept bool isUsingPointer() const noexcept
@ -167,13 +174,7 @@ class QVersionNumber
inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len); inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len);
} }
void resize(qsizetype len) Q_CORE_EXPORT void resize(qsizetype len);
{
if (isUsingPointer())
pointer_segments->resize(len);
else
setInlineSize(len);
}
int at(qsizetype index) const int at(qsizetype index) const
{ {