summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-12-05 18:21:11 -0800
committerThiago Macieira <thiago.macieira@intel.com>2023-12-21 11:13:32 -0800
commit5ea4e27661e1805a6ed01c7a61643f9a50c15d62 (patch)
tree442dbe25ae1ee1acc351842ac2e46750c0b88999
parentdfe968e9702c740b3522715fa9f0e9a281c92885 (diff)
QByteArray: inline QByteArray::indexOf() and use a char overload
QByteArray::indexOf() had the best implementation of the two *because* it was out-of-line, in qbytearray.cpp. The compiler could thus see the body of the QtPrivate::findByteArray() function and inline it, with constant-propagation, so only findCharHelper() was expanded and we had a fast path towards memchr(). On the other hand, QByteArrayView::indexOf() was inline, so the compiler emitted the call to QtPrivate::findByteArray() in user code, causing the full function to be executed. We fix that by adding a char overload for QtPrivate::findByteArray() and lastIndexOf(), so we get to memchr() more quickly. Also, inline QByteArray::indexOf() and lastIndexOf(). Before: QByteArray::indexOf(): 8.83287376 nsecs per iteration 22.01766832 CPU cycles per iteration, 2.49 GHz 62.00000330 instructions per iteration, 2.816 instr/cycle 21.00000281 branch instructions per iteration, 2.38 G/sec QByteArrayView::indexOf(): 9.64034694 nsecs per iteration 24.03001151 CPU cycles per iteration, 2.49 GHz 68.00000355 instructions per iteration, 2.830 instr/cycle 23.00000306 branch instructions per iteration, 2.39 G/sec After (same result for both, requires recompilation): 8.83207052 nsecs per iteration 22.01568546 CPU cycles per iteration, 2.49 GHz 60.00000331 instructions per iteration, 2.725 instr/cycle 21.00000281 branch instructions per iteration, 2.38 G/sec The inlining appears to have cut 2 instructions, but the effect is not measurable in this benchmark (the entire code is in cache and the Branch Predictor is probably primed). Fixes: QTBUG-119750 Change-Id: Ica7a43f6147b49c187ccfffd179e1cb4b306fc62 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r--src/corelib/compat/removed_api.cpp2
-rw-r--r--src/corelib/text/qbytearray.cpp22
-rw-r--r--src/corelib/text/qbytearray.h12
-rw-r--r--src/corelib/text/qbytearrayalgorithms.h6
-rw-r--r--src/corelib/text/qbytearrayview.h4
5 files changed, 33 insertions, 13 deletions
diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp
index 2f62a3055d..87b2d14916 100644
--- a/src/corelib/compat/removed_api.cpp
+++ b/src/corelib/compat/removed_api.cpp
@@ -625,7 +625,7 @@ QBitArray QBitArray::operator~() const
return QBitArray(*this).inverted_inplace();
}
-#include "qbytearray.h"
+#include "qbytearray.h" // also includes inlined API
QByteArray QByteArray::left(qsizetype len) const
{
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 69d21cbe24..a1ae331585 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -2656,6 +2656,11 @@ static inline qsizetype findCharHelper(QByteArrayView haystack, qsizetype from,
return -1;
}
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ return findCharHelper(haystack, from, needle);
+}
+
qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
const auto ol = needle.size();
@@ -2690,6 +2695,7 @@ qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByt
*/
/*!
+ \fn qsizetype QByteArray::indexOf(char ch, qsizetype from) const
\overload
Returns the index position of the start of the first occurrence of the
@@ -2702,11 +2708,6 @@ qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByt
\sa lastIndexOf(), contains()
*/
-qsizetype QByteArray::indexOf(char ch, qsizetype from) const
-{
- return qToByteArrayViewIgnoringNull(*this).indexOf(ch, from);
-}
-
static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char *needle,
qsizetype ol, qsizetype from)
{
@@ -2760,6 +2761,11 @@ static inline qsizetype lastIndexOfCharHelper(QByteArrayView haystack, qsizetype
return -1;
}
+qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ return lastIndexOfCharHelper(haystack, from, needle);
+}
+
qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
if (haystack.isEmpty()) {
@@ -2813,6 +2819,7 @@ qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteA
*/
/*!
+ \fn qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const
\overload
Returns the index position of the start of the last occurrence of byte \a ch
@@ -2826,11 +2833,6 @@ qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteA
\sa indexOf(), contains()
*/
-qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const
-{
- return qToByteArrayViewIgnoringNull(*this).lastIndexOf(ch, from);
-}
-
static inline qsizetype countCharHelper(QByteArrayView haystack, char needle) noexcept
{
qsizetype num = 0;
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index aeeeb15e0e..06d310856b 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -133,10 +133,12 @@ public:
[[nodiscard]] char back() const { return at(size() - 1); }
[[nodiscard]] inline char &back();
+ QT_CORE_INLINE_SINCE(6, 7)
qsizetype indexOf(char c, qsizetype from = 0) const;
qsizetype indexOf(QByteArrayView bv, qsizetype from = 0) const
{ return QtPrivate::findByteArray(qToByteArrayViewIgnoringNull(*this), from, bv); }
+ QT_CORE_INLINE_SINCE(6, 7)
qsizetype lastIndexOf(char c, qsizetype from = -1) const;
qsizetype lastIndexOf(QByteArrayView bv) const
{ return lastIndexOf(bv, size()); }
@@ -688,6 +690,16 @@ bool QByteArray::isNull() const noexcept
return d->isNull();
}
#endif
+#if QT_CORE_INLINE_IMPL_SINCE(6, 7)
+qsizetype QByteArray::indexOf(char ch, qsizetype from) const
+{
+ return qToByteArrayViewIgnoringNull(*this).indexOf(ch, from);
+}
+qsizetype QByteArray::lastIndexOf(char ch, qsizetype from) const
+{
+ return qToByteArrayViewIgnoringNull(*this).lastIndexOf(ch, from);
+}
+#endif
#if !defined(QT_NO_DATASTREAM) || defined(QT_BOOTSTRAPPED)
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &);
diff --git a/src/corelib/text/qbytearrayalgorithms.h b/src/corelib/text/qbytearrayalgorithms.h
index 081fb66f81..db8b239fd8 100644
--- a/src/corelib/text/qbytearrayalgorithms.h
+++ b/src/corelib/text/qbytearrayalgorithms.h
@@ -26,9 +26,15 @@ bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
bool endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype findByteArray(QByteArrayView haystack, qsizetype from, char needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
qsizetype findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
diff --git a/src/corelib/text/qbytearrayview.h b/src/corelib/text/qbytearrayview.h
index d8ad65ae1e..0541436df9 100644
--- a/src/corelib/text/qbytearrayview.h
+++ b/src/corelib/text/qbytearrayview.h
@@ -263,7 +263,7 @@ public:
[[nodiscard]] qsizetype indexOf(QByteArrayView a, qsizetype from = 0) const noexcept
{ return QtPrivate::findByteArray(*this, from, a); }
[[nodiscard]] qsizetype indexOf(char ch, qsizetype from = 0) const noexcept
- { return QtPrivate::findByteArray(*this, from, QByteArrayView(&ch, 1)); }
+ { return QtPrivate::findByteArray(*this, from, ch); }
[[nodiscard]] bool contains(QByteArrayView a) const noexcept
{ return indexOf(a) != qsizetype(-1); }
@@ -275,7 +275,7 @@ public:
[[nodiscard]] qsizetype lastIndexOf(QByteArrayView a, qsizetype from) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, a); }
[[nodiscard]] qsizetype lastIndexOf(char ch, qsizetype from = -1) const noexcept
- { return QtPrivate::lastIndexOf(*this, from, QByteArrayView(&ch, 1)); }
+ { return QtPrivate::lastIndexOf(*this, from, ch); }
[[nodiscard]] qsizetype count(QByteArrayView a) const noexcept
{ return QtPrivate::count(*this, a); }