diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2021-07-20 17:06:49 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2021-07-26 20:43:44 +0000 |
commit | 5d0542a356be1c47e2f99e6ba38b8e520ca0710c (patch) | |
tree | 1e756b3dbb83f211d330106d5203cbfdf95c327d /src/corelib/text/qlocale_tools.cpp | |
parent | 7ff72d0a0f1f4964e4d4fd250283711fc51db016 (diff) |
QString::number(int): Avoid going through qlocale machinery
For increased performance, as measured with the number_qu?longlong
QString benchmarks.
The results are all good, reducing runtime by anywhere between 40
and 220 nanoseconds. The slowest test previously completing at ~330ns,
now completing at ~105ns.
Task-number: QTBUG-88484
Change-Id: Ie96e86e57b635bac01389aed531a6d9f087df983
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/text/qlocale_tools.cpp')
-rw-r--r-- | src/corelib/text/qlocale_tools.cpp | 92 |
1 files changed, 48 insertions, 44 deletions
diff --git a/src/corelib/text/qlocale_tools.cpp b/src/corelib/text/qlocale_tools.cpp index 24a6bcfd09..bdb00d3696 100644 --- a/src/corelib/text/qlocale_tools.cpp +++ b/src/corelib/text/qlocale_tools.cpp @@ -460,6 +460,53 @@ qstrtoll(const char * nptr, const char **endptr, int base, bool *ok) return result; } +static Q_ALWAYS_INLINE void qulltoBasicLatin_helper(qulonglong number, int base, char16_t *&p) +{ + // Performance-optimized code. Compiler can generate faster code when base is known. + switch (base) { +#define BIG_BASE_LOOP(b) \ + do { \ + const int r = number % b; \ + *--p = (r < 10 ? u'0' : u'a' - 10) + r; \ + number /= b; \ + } while (number) +#ifndef __OPTIMIZE_SIZE__ +#define SMALL_BASE_LOOP(b) \ + do { \ + *--p = u'0' + number % b; \ + number /= b; \ + } while (number) + + case 2: SMALL_BASE_LOOP(2); break; + case 8: SMALL_BASE_LOOP(8); break; + case 10: SMALL_BASE_LOOP(10); break; + case 16: BIG_BASE_LOOP(16); break; +#undef SMALL_BASE_LOOP +#endif + default: BIG_BASE_LOOP(base); break; +#undef BIG_BASE_LOOP + } +} + +// This is technically "qulonglong to ascii", but that name's taken +QString qulltoBasicLatin(qulonglong number, int base, bool negative) +{ + if (number == 0) + return QStringLiteral("0"); + // Length of MIN_LLONG with the sign in front is 65; we never need surrogate pairs. + // We do not need a terminator. + const unsigned maxlen = 65; + static_assert(CHAR_BIT * sizeof(number) + 1 <= maxlen); + char16_t buff[maxlen]; + char16_t *const end = buff + maxlen, *p = end; + + qulltoBasicLatin_helper(number, base, p); + if (negative) + *--p = u'-'; + + return QString(reinterpret_cast<QChar *>(p), end - p); +} + QString qulltoa(qulonglong number, int base, const QStringView zero) { // Length of MAX_ULLONG in base 2 is 64; and we may need a surrogate pair @@ -469,51 +516,8 @@ QString qulltoa(qulonglong number, int base, const QStringView zero) char16_t buff[maxlen]; char16_t *const end = buff + maxlen, *p = end; - // Performance-optimized code. Compiler can generate faster code when base is known. if (base != 10 || zero == u"0") { - switch (base) { -#ifndef __OPTIMIZE_SIZE__ - case 10: - while (number != 0) { - const int c = number % 10; - const qulonglong temp = number / 10; - *--p = '0' + c; - number = temp; - } - break; - case 2: - while (number != 0) { - const int c = number % 2; - const qulonglong temp = number / 2; - *--p = '0' + c; - number = temp; - } - break; - case 8: - while (number != 0) { - const int c = number % 8; - const qulonglong temp = number / 8; - *--p = '0' + c; - number = temp; - } - break; - case 16: - while (number != 0) { - const int c = number % 16; - const qulonglong temp = number / 16; - *--p = c < 10 ? '0' + c : c - 10 + 'a'; - number = temp; - } - break; -#endif - default: - while (number != 0) { - const int c = number % base; - const qulonglong temp = number / base; - *--p = c < 10 ? '0' + c : c - 10 + 'a'; - number = temp; - } - } + qulltoBasicLatin_helper(number, base, p); } else if (zero.size() && !zero.at(0).isSurrogate()) { const char16_t zeroUcs2 = zero.at(0).unicode(); while (number != 0) { |