diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-01-16 13:17:16 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-01-18 01:31:33 +0100 |
commit | 6f6c8d061803a3c89f260fa234388dc27c308bce (patch) | |
tree | 9f1c5d1b359471c224d6b0b72dfe6b35cacd7dcb | |
parent | 9ffcab65629539c0335c78d9896153d9c31f475e (diff) |
QVersionNumber: don't allocate in fromString() in the common case
Use QVarLengthArray instead of QList to avoid allocations in the case
where the result fits into inline storage.
Of course, we now perform one allocation more when we need the QList
backend, but a) that should be the rarer case and b) we use 32 (more
than InlineSegmentsCount) Prealloc for the QVarLengthArray to reliably
skip the first few QList non-reserved capacity jumps (measured to be
{4, 12, 28} for back-insertion, not all of which is probably available
for append()s) to come out ahead either way.
Reviewers may object, saying that we could just reserve(32) the QList,
too, but while that would skip over the first few QList reallocations
alright, it means we'd be carrying the extra capacity around for the
duration of the QVersionNumber's lifetime (unless we'd shrink it at
the end, bringing back the additional allocation and that solution
back to par compared to this one).
As a consequence:
[ChangeLog][QtCore][QVersionNumber] Can now be also be constructed
from QVarLengthArray.
Change-Id: I4016367f64f6cefa6ed9147d33b06636f36b02cb
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/tools/qversionnumber.cpp | 17 | ||||
-rw-r--r-- | src/corelib/tools/qversionnumber.h | 16 |
2 files changed, 27 insertions, 6 deletions
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 4aa8cdd346..38977c3db8 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -120,6 +120,13 @@ QT_BEGIN_NAMESPACE */ /*! + \fn template <qsizetype N> QVersionNumber::QVersionNumber(const QVarLengthArray<int, N> &seg) + \since 6.4 + + Constructs a version number from the list of numbers contained in \a seg. +*/ + +/*! \fn bool QVersionNumber::isNull() const Returns \c true if there are zero numerical segments, otherwise returns @@ -421,7 +428,13 @@ QString QVersionNumber::toString() const static QVersionNumber from_string(QLatin1String string, qsizetype *suffixIndex) { - QList<int> seg; + // 32 should be more than enough, and, crucially, it means we're allocating + // not more (and often less) often when compared with direct QList usage + // for all possible segment counts (under the constraint that we don't want + // to keep more capacity around for the lifetime of the resulting + // QVersionNumber than required), esp. in the common case where the inline + // storage can be used. + QVarLengthArray<int, 32> seg; const char *start = string.begin(); const char *end = start; @@ -441,7 +454,7 @@ static QVersionNumber from_string(QLatin1String string, qsizetype *suffixIndex) if (suffixIndex) *suffixIndex = lastGoodEnd - string.begin(); - return QVersionNumber(std::move(seg)); + return QVersionNumber(seg); } static QVersionNumber from_string(q_no_char8_t::QUtf8StringView string, qsizetype *suffixIndex) diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index ad8367c135..f00ce36437 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -141,12 +141,15 @@ class QVersionNumber else pointer_segments = new QList<int>(std::move(seg)); } - SegmentStorage(std::initializer_list<int> args) + explicit SegmentStorage(std::initializer_list<int> args) + : SegmentStorage(args.begin(), args.end()) {} + + explicit SegmentStorage(const int *first, const int *last) { - if (dataFitsInline(std::data(args), args.size())) { - setInlineData(std::data(args), args.size()); + if (dataFitsInline(first, last - first)) { + setInlineData(first, last - first); } else { - pointer_segments = new QList<int>(args); + pointer_segments = new QList<int>(first, last); } } @@ -234,6 +237,11 @@ public: : m_segments(args) {} + template <qsizetype N> + explicit QVersionNumber(const QVarLengthArray<int, N> &sec) + : m_segments(sec.begin(), sec.end()) + {} + inline explicit QVersionNumber(int maj) { m_segments.setSegments(1, maj); } |