When a timer gets unregistered there is a chance that a new timer is
registered again immediately and gets the same ID.
On Windows this is a problem because there may be WM_TIMER messages
remaining in the native event loop that have not been processed.
This may result in unexpected timeouts for newly started timers.
By not masking away the serial/generation from the ID we generate
we will no longer return the same ID that was just freed.
While QFreeList mostly was prepared to be used in this way, one function
was not, and the tests were written with the assumption that the serial
was masked out. So this patch also addresses that.
Fixes: QTBUG-124496
Pick-to: 6.7 6.5
Change-Id: If6784815bfa41e497cbc4e00bef51da3ded5f255
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
(cherry picked from commit 21e9875d62414306fde9738ab255e55f22d1c8ed)
The logic in the isValidSegment() function was failing for 8-bit signed
because for them Integer(SegmentUnknown) is -1, so
(std::numeric_limits<Integer>::max)() < Integer(SegmentUnknown)
was always false (127 < -1) and the function would only return true on
the impossible condition of
segment >= 0 && segment < -1
Fixes: QTBUG-128848
Pick-to: 6.7 6.5
Change-Id: I8d17b93afd6c2982a099fffdcaeccf126b7a9d02
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit ddfcc0734875cdee2c169bf2ecb1546bddba6e98)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This removes the specializations, which were hiding the fact that signed
8-bit integers produce assertion failures.
Pick-to: 6.7 6.5
Task-number: QTBUG-128848
Change-Id: Ibb4952b0eb50a8c51e05fffd9e88a137ca95bcd8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit a572b4b0780dcc5fcac55737fc4153fca93e6c62)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
That allows the code to run in C++17 mode - at the expense of
significantly worse compile time error messages, potentially worse
compilation speed and harder to read code.
Adjust the test type to actually model
detail::is_equality_comparable_with (which requires all four
relational operators even in C++17).
As a drive-by, fix the return value of remove() from auto to bool.
Done-with: Marc Mutz <marc.mutz@qt.io>
Fixes: QTBUG-128470
Change-Id: I68df26db579c60812a18e09b76dd5712e73ccaa2
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 7fe3cee36352c74cbaaff52e863bd0da1170affa)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Follow the dynamicCast/dynamic_pointer_cast implementation for
objectCast/object_pointer_cast since a qobject_cast can fail
just like a dynamic dast.
Also see: https://eel.is/c++draft/util.smartptr.shared.cast#6.2
See commit this commit from 2013 for more historical context:
a094bf5a89
Pick-to: 6.7 6.5
Change-Id: I9a54af55a7a1cf106cace52e9cf3bc103ae0bd42
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 7a65abb50eb638de445e24c2746d7f90c1b89f06)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Iterators no longer provide it, because they may need to return a
temporary in some occasions.
Fixes: QTBUG-128102
Change-Id: Ide0a7a84f612fff73afffffd49889321cb70505f
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
(cherry picked from commit cb40a1fa7f4b06acced1d17e8333742084092f9e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The macro is defined or not, not defined to 1 or 0.
Amends 1d7950c946 (qhashfunctions.h),
0d85d0a72f (tst_qfloat16.cpp),
104a0a9ecd (tst_qglobal.cpp),
7a829eaf51 (tst_qtendian.cpp).
Pick-to: 6.7
Change-Id: I190e208f3c96f27100dae3eef512739afa8fadd9
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
(cherry picked from commit c78994a887f56f1bc77a5fa0db3b98196851db5e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
We cannot use memcmp() for that, as it incorrectly results in two
NaN values being equal.
Simply replace the whole self-written algorithm with std::equal(),
as it's doing the same thing, but lets the compiler decide when
to do the optimizations.
Amends db89349bdb.
[ChangeLog][QtCore][QList] Fixed a bug when two QLists holding NaN
values were considered to be equal.
Fixes: QTBUG-127473
Pick-to: 6.7 6.5 6.2
Change-Id: If7e77549b4cbeb96711893d14344b9e0a40c1a87
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit cb3faeba3d9411ba82c311751bd7de36d0fec939)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
For legacy reasons, the accessor class allows operator[] to go out of
bounds and just returns an empty string. However, we were returning a
pointer to the one-past-end of the array, which appears to have been a
null byte in the test.
Instead of adding branching code to load the length of the first string
in operator[], we can just add an extra null character at the position
we were returning anyway.
Pick-to: 6.5
Change-Id: I4878533dcb2d4b3e8efefffd17e4f876b43e9ee3
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
(cherry picked from commit 8a768fe7db6ac5388fec6a68687817796b44439e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The tests are needed for the next patch where we modernize comparisons
and wrap the pointer, which involves changing most of the functions.
Pick-to: 6.7 6.5 6.2
Change-Id: If635538bfca33e410e19472d32b9666d258f96a9
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
(cherry picked from commit b44541d8a42b7fc0b24cde4086b0030623280cc0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
The build on Android with clang results in a bunch of irrelevant
warnings. Disable them for the offending lines of test code.
Change-Id: Ica5d867e3a2b1215dc526cc5f945a39ac908ac23
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 8d523a098cc8068400a6138970c6382f8f56224c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
... by adding more arguments, but then constraining that they don't,
actually, exist.
This makes the the signature of a normal qHash(T, size_t) consistently
a better overload (for same T) than the 1-to-2 adapter. It doesn't
solve the problem that the adapter inserts hash functions for types
that were never defined to be hashable (cf. e.g. QTBUG-116076). But
the adapter is already slated for removal in Qt 7, which will solve
the issue, though maybe we can expedite its demise in 6.9.
Add the test from the bugreport to tst_QHashFunctions.
Fixes: QTBUG-126659
Change-Id: Idb3f275f0409652d55b318d56092764371269c06
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 798c23189c7fb73629c1a98361cb1f50446fecf1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This fell out of my tracking of a failure of the new QPointer
conversion feature, and it would be a waste to throw it away unused.
Pick-to: 6.7 6.5 6.2 5.15
Change-Id: Ie255b4a6432b4763071e5712d92e9ccd57927052
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
(cherry picked from commit 0e40a3f6645a684458cbb09bef1353df2eec5e0b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Dogfooding the new QtTest 6.8 feature, and greatly simplifiying the
source code.
Change-Id: I0731d7291048e6bbed19666d1b6672e5cccaf27a
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
(cherry picked from commit 157fcdf5afbe4e6b421713947ccdb4ee35116ee4)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Commit 54c373faa4 updated the bitwise
operations to be more efficient, bypassing QByteArray and going straight
to QByteArrayData (a.k.a. QArrayDataPointer<char>). This meant we also
bypassed the initialization of the null terminator.
This wasn't caught in our unit testing and with some runtimes because
the memory we allocated happened to be zero or contain the information
we wanted. But with Visual Studio, the debug-mode runtime initializes
all newly allocated memory with pattern 0xcd, which showed up as a
problem.
[ChangeLog][QtCore][QBitArray] Fixed a regression introduced in 6.7.0
that could cause QBitArray to report wrong bit counts after a bitwise
operation.
Pick-to: 6.7
Fixes: QTBUG-126343
Change-Id: Icdc467f26dea4b05ad90fffd17d939c3b416adca
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 8ac57ff6bc778519bb1edc4036ce79ab8f688e27)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Until now, QCryptographicHash had a big drawback over the underlying
C APIs: at least one extra memory allocation: Either you created a
QCryptographicHash object (allocates a Private), and enjoy noexcept
addData() and resultView(), or you used the static hash() function
(which creates a Private on the stack, so doesn't need to allocate
one), but then we needed to return in an owning container.
Enter QSpan and hashInto(), which allow the user to provide a buffer
into which to write, and therefore can be completely noexcept and
(apart from a missing optimization which, however, doesn't affect the
API) deliver near C-API efficiency.
We don't have QMutableByteArrayView, which would deal with the
different types of equivalent char types for us, so we overload for
QSpan<std::bytes>, QSpan<char> and QSpan<uchar>, which makes the
overload set accept roughly what QByteArrayView would accept, too.
Return by QByteArrayView because that has a richer API than QSpan,
which lacks (on purpose) string-ish API.
[ChangeLog][QtCore][QCryptographicHash] Added hashInto().
Task-number: QTBUG-125431
Change-Id: I80ecc7151d3418a36c4d5db6d22d0b82c869b19f
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
For std::span, these are free functions in namespace std and therefore
work for anything implicitly convertible to std::span,
incl. QSpan. But they're C++20, QSpan needs something for C++17
builds.
By adding them as hidden friends for QSpan, we allow unqualifid calls
to transparently resolve to the respective overload, ensuring
source-compatibility between std:: and QSpan, and, eventually, a
transition back to std::as_*_bytes.
I considered the alternative to add these functions in the q20
namespace, but q20::as_bytes() would have to take QSpan, and QSpan is
convertible from more types than std::span, so we wouldn't be able to
guarantee that std::as_bytes(t) works for all T t for which
q20::as_bytes(t) works, the fundamental guarantee for namespace qNN.
[ChangeLog][QtCore][QSpan] Added std::span-style as_bytes() and
as_writable_bytes() functions.
Fixes: QTBUG-125489
Change-Id: Ia9a7560c7843e182892608178433be7349c825ba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
We've already tested fixed-size-0 spans for default-constructibility
two lines before. We need to check dynamically-sized spans here.
This doesn't extend test coverage: in the course of the function we've
already default-constructed the correct type.
Amends f82cf6333e.
Pick-to: 6.7
Change-Id: Ibb192b1661f12babb449752bf107eca404a95ad2
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
We know NumAlgorithms is not supported, so don't print a skipped
warning, by not including that enumerator in the test data in the
first place.
Amends 96dc4acb23.
Pick-to: 6.7
Change-Id: Ie19f7ebcceb855b9363017c8b2626dae99e23313
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
The test already exercised the function here and there, but it lacked
a central place to test the static hash() method, so add one.
Pick-to: 6.7 6.5
Change-Id: I229bc8a8ed07e0036f60de62ecc4d11ef88dd20e
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
GCC 11 doesn't understand that 'i' isn't ever read from (because all
spans created over it have size zero), but initialize it nonetheless
to suppress the warning.
Amends f82cf6333e.
Pick-to: 6.7
Change-Id: Ibfb3e9b7fdcbe93c43b7873986c74b4b5a0c9e54
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
[ChangeLog][QtCore][QSizeF] Added qFuzzyCompare and qFuzzyIsNull
overloads for QSizeF
Drop the custom qFuzzyCompare() implementation from
tst_qgraphicsgridlayout.cpp
Task-number: QTBUG-120308
Change-Id: I32d11c1c81d0503914a8168b5e960a8c6ce943d9
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Also explicitly add QSizeF vs QSize comparison. Previously such
comparison was implicitly converting QSize to QSizeF, and doing the
fuzzy comparison. We have to keep the old behavior to avoid
breaking user code, so use fuzzy comparison in the new operators
as well.
As a drive-by: put all the hidden friends in the private section.
Done-with: Ivan Solovev <ivan.solovev@qt.io>
Task-number: QTBUG-120308
Change-Id: Ia52adc97c557e475b19f5c16f9dd8c992637280e
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Like with the QLine(F) case, we have to use QT_CORE_REMOVED_SINCE to
remove the old member operators, but also need to guard the new friend
functions with !(QT_CORE_REMOVED_SINCE), because QEasingCurve is also
one of the core types, and on Windows the metatype interface for it is
instantiated in removed_api.cpp.
Task-number: QTBUG-120308
Change-Id: I1bd66f7230afd3eba868d05fd496ab13a0331178
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Also explicitly add QMarginsF vs QMargins comparison. Previously such
comparison was implicitly converting QMargins to QMarginsF, and doing the
fuzzy comparison. We have to keep the old behavior to avoid
breaking user code, so use fuzzy comparison in the new operators
as well.
Task-number: QTBUG-120308
Change-Id: Ic82f64078cd991859b851f24aa7017ef0b91a4e1
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
The (in)equality operators for QMarginsF are documented to use fuzzy
comparison. However, the implementation unconditionally used
qFuzzyCompare which is incorrect for the case of 0 margins.
Update the implementation to use a combination of qFuzzyIsNull and
qFuzzyCompare, like it's done for QPointF.
[ChangeLog][QtCore][QMarginsF] Fixed a bug when equality comparison
returned incorrect results if one of the margins was zero.
Task-number: QTBUG-120308
Change-Id: I6e785fe8b523f6aa5f5317fb75877fdbf4e086c2
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Also explicitly add QRectF vs QRect comparison. Previously such
comparison was implicitly converting QRect to QRectF, and doing the
fuzzy comparison.
The new operators are directly calling operator==(QPointF, QPoint),
which also does the fuzzy comparison, so the old behavior is preserved.
As a drive-by: move the operators into the private section.
Task-number: QTBUG-120308
Change-Id: I9b96ed4266e6a6c02a52c8cfff6ec1b2d036a7ca
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
QLineF::isNull was using qFuzzyCompare on the x and y components of its
points, which was not working correctly if some of the components was
equal to zero. The correct approach is to use qFuzzyIsNull togeter with
qFuzzyCompare. This approach is already implemented in qFuzzyCompare()
overload for QPointF, so just use it.
Add unit-tests for QLine(F)::isNull.
[ChangeLog][QtCore][QLineF] Fixed a bug when QLineF::isNull() returned
incorrect result if the start or end point contained a zero component.
Change-Id: I3cfe6406b1299de32fe82b1fcbfb0416f0eaac15
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Also explicitly add QLineF vs QLine comparison. Previously such
comparison was implicitly converting QLine to QLineF, and doing the
fuzzy comparison.
The new operators are directly calling operator==(QPointF, QPoint),
which also does the fuzzy comparison, so the old behavior is preserved.
Remove the old relational operators using QT_CORE_REMOVED_SINCE, but
also wrap the new operators in !defined(QT_CORE_REMOVED_SINCE).
That is required, because on Windows the instantiation of
QMetaTypeInterface<QLine(F)> happens in removed_api.cpp (as both
qline.h and qmetatype.h are already included there). If we just add
removed member operators into removed_api.cpp, the metatype interface
will not be able to create an equals() function, because of the
ambiguity in equality operators (member vs friend). That's why we have
to exclude the new friend operators from removed_api.cpp.
Done-with: Fabian Kosmale <fabian.kosmale@qt.io>
Task-number: QTBUG-120308
Change-Id: Ibbf5ec077f69c75da0d36a8be5596acd0fcd44d0
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Use the new qFuzzyCompare() overload in op==(QPointF, QPointF).
[ChangeLog][QtCore][QPointF] Added qFuzzyCompare() and qFuzzyIsNull()
overloads for QPointF.
Task-number: QTBUG-120308
Change-Id: I522164acb65432bf55c58b55575f25535d27e27a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Explicitly add QPointF vs QPoint comparison. Previously such
comparison was implicitly converting QPoint to QPointF, and
doing the fuzzy comparison. We have to keep the old behavior to
avoid breaking user code, so explicitly use fuzzy comparison in
the new operators.
As a drive-by: move the friend functions into the private section,
so that they are actually hidden friends.
Task-number: QTBUG-120308
Change-Id: I471a890b8332455e8b2dc1b99e5fba4ada168a30
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
Now developer build tests compile, but some are not working.
Functional fix will come later via separate tasks.
Task-number: QTBUG-122999
Change-Id: I70487b46c1b32ba4279cb02a4978e4f55ac0d310
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Replace public friend operators operator==(), operator!=() of
QBitArray to friend method comparesEqual() and
Q_DECLARE_EQUALITY_COMPARABLE macro.
Task-number: QTBUG-120304
Change-Id: I6b47111c144016b3aa05f01c8035c32d164291ad
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
C++11 has been required for a long time.
Pick-to: 6.7 6.6 6.5
Change-Id: Ib6c1571b100dd4eb8194d515f2180ca26481b556
Reviewed-by: David Faure <david.faure@kdab.com>
QTypeRevision consists of two quint8 values: major and minor version.
Each of the versions can be unknown.
The rules for comparing with the unknown version are as follows:
zero version < unknown version < non-zero version
At the same time, two unknown versions are considered equal.
This makes the comparison a bit tricky, but it still fits into the
category of strong ordering.
Replace the existing friend relational operators with helper functions
and comparison helper macros, making this type strongly ordered.
Update the unit-tests to use the new comparison helper test functions.
As the test functions check the reversed arguments as well, we can
reduce the number of rows for the data-driven comparison test.
Fixes: QTBUG-120359
Change-Id: Ib6f1037fc7b5fed148e35ee48b56b05dcd36b3b4
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This patch simplifies the checks when migrating the class to comparison
helper macros.
Task-number: QTBUG-120359
Change-Id: I47a6ba20d3b89c31edc2f432621eae9385fbd0a3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
It's the same aeshash() as before, except we're passing a template
parameter to indicate whether to read half and then zero-extend the
data. That is, it will perform a conversion from Latin1 on the fly.
When running in zero-extending mode, the length parameters are actually
doubled (counting the number of UTF-16 code units) and we then divide
again by 2 when advancing.
The implementation should have the following performance
characteristics:
* QLatin1StringView now will be roughly half as fast as Qt 6.7
* QLatin1StringView now will be roughly as fast as QStringView
For the aeshash128() in default builds of QtCore (will use SSE4.1), the
long loop (32 characters or more) is:
QStringView QLatin1StringView
movdqu -0x20(%rax),%xmm4 | pmovzxbw -0x10(%rdx),%xmm2
movdqu -0x10(%rax),%xmm5 | pmovzxbw -0x8(%rdx),%xmm3
add $0x20,%rax | add $0x10,%rdx
pxor %xmm4,%xmm0 | pxor %xmm2,%xmm0
pxor %xmm5,%xmm1 | pxor %xmm3,%xmm1
aesenc %xmm0,%xmm0 aesenc %xmm0,%xmm0
aesenc %xmm1,%xmm1 aesenc %xmm1,%xmm1
aesenc %xmm0,%xmm0 aesenc %xmm0,%xmm0
aesenc %xmm1,%xmm1 aesenc %xmm1,%xmm1
The number of instructions is identical, but there are actually 2 more
uops per iteration. LLVM-MCA simulation shows this should execute in the
same number of cycles on older CPUs that do not have support for VAES
(see <https://analysis.godbolt.org/z/x95Mrfrf7>).
For the VAES version in aeshash256() and the AVX10 version in
aeshash256_256():
QStringView QLatin1StringView
vpxor -0x40(%rax),%ymm1,%ym | vpmovzxbw -0x20(%rax),%ymm3
vpxor -0x20(%rax),%ymm0,%ym | vpmovzxbw -0x10(%rax),%ymm2
add $0x40,%rax | add $0x20,%rax
| vpxor %ymm3,%ymm0,%ymm0
| vpxor %ymm2,%ymm1,%ymm1
vaesenc %ymm1,%ymm1,%ymm1 <
vaesenc %ymm0,%ymm0,%ymm0 vaesenc %ymm0,%ymm0,%ymm0
vaesenc %ymm1,%ymm1,%ymm1 vaesenc %ymm1,%ymm1,%ymm1
vaesenc %ymm0,%ymm0,%ymm0 vaesenc %ymm0,%ymm0,%ymm0
> vaesenc %ymm1,%ymm1,%ymm1
In this case, the increase in number of instructions matches the
increase in number of uops. The LLVM-MCA simulation says that the
QLatin1StringView version is faster at 11 cycles/iteration vs 14 cyc/it
(see <https://analysis.godbolt.org/z/1Gv1coz13>), but that can't be
right.
Measured performance of CPU cycles, on an Intel Core i9-7940X (Skylake,
no VAES support), normalized on the QString performance (QByteArray is
used as a stand-in for the performance in Qt 6.7):
aeshash | siphash
QByteArray QL1SV QString QByteArray QString
dictionary 94.5% 79.7% 100.0% 150.5%* 159.8%
paths-small 90.2% 93.2% 100.0% 202.8% 290.3%
uuids 81.8% 100.7% 100.0% 215.2% 350.7%
longstrings 42.5% 100.8% 100.0% 185.7% 353.2%
numbers 95.5% 77.9% 100.0% 155.3%* 164.5%
On an Intel Core i7-1165G7 (Tiger Lake, capable of VAES and AVX512VL):
aeshash | siphash
QByteArray QL1SV QString QByteArray QString
dictionary 90.0% 91.1% 100.0% 103.3%* 157.1%
paths-small 99.4% 104.8% 100.0% 237.5% 358.0%
uuids 88.5% 117.6% 100.0% 274.5% 461.7%
longstrings 57.4% 111.2% 100.0% 503.0% 974.3%
numbers 90.6% 89.7% 100.0% 98.7%* 149.9%
On an Intel 4th Generation Xeon Scalable Platinum (Sapphire Rapids, same
Golden Cove core as Alder Lake):
aeshash | siphash
QByteArray QL1SV QString QByteArray QString
dictionary 89.9% 102.1% 100.0% 158.1%* 172.7%
paths-small 78.0% 89.4% 100.0% 159.4% 258.0%
uuids 109.1% 107.9% 100.0% 279.0% 496.3%
longstrings 52.1% 112.4% 100.0% 564.4% 1078.3%
numbers 85.8% 98.9% 100.0% 152.6%* 190.4%
* dictionary contains very short entries (6 characters)
* paths-small contains strings of varying length, but very few over 32
* uuids-list contains fixed-length strings (38 characters)
* longstrings is the same but 304 characters
* numbers also a lot contains very short strings (1 to 6 chars)
What this shows:
* For short strings, the performance difference is negligible between
all three
* For longer strings, QLatin1StringView now costs between 7 and 17% more
than QString on the tested machines instead of up to ~50% less, except on
the older machine (where I think the main QString hashing is suffering
from memory bandwidth limitations)
* The AES hash implementation is anywhere from 1.6 to 11x faster than
Siphash
* Murmurhash (marked with asterisk) is much faster than Siphash, but it
only managed to beat the AES hash in one test
Change-Id: I664b9f014ffc48cbb49bfffd17b045c1811ac0ed
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
So that it hashes to the same value as QString{,View}.
In order to test this, you must either run on a CPU other than ARM and
x86, or disable the AES hasher. I did that and can confirm siphash and
murmurhash do work with on-the-fly conversion from Latin-1.
Change-Id: I664b9f014ffc48cbb49bfffd17b03e5e62ec4e89
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This complements the previous commit by adding the heterogeneous lookup
in operator[]. Unlike the members of the previous commit, this one may
insert into the hash, in which case it needs a way to cast from the
heterogeneous type K to the actual Key type.
Change-Id: I664b9f014ffc48cbb49bfffd17b037c1063dfb91
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This implements support in QHash and QMultiHash for lookups of
heterogeneous key types that produce the same hash value. This is
implemented by duplicating each of the following functions into an
overload on Key and one a template that is enable_if-constrained to a
key type that meets the requirement:
* contains
* count
* equals_range
* find
* operator[] (const only)
* remove
* take
* value
* values (QMultiHash)
The non-const operator[] may insert into the hash, so it's not part of
this commit.
Change-Id: I664b9f014ffc48cbb49bfffd17b037852f0fd192
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>