[Development] How qAsConst and qExchange lead to qNN
marc.mutz at qt.io
Wed Nov 16 19:11:53 CET 2022
On 14.11.22 19:00, Volker Hilsheimer wrote:
> Today, the vast majority of client code already has an owning container that gets passed around by copy or as const references.
There are important subsets that don't, e.g. the aforementioned
serialisation APIs and where 10%+ executable code savings can be had:
> In Qt, we usually store data in the implementation in QList and QString. A test case that artificially creates a ton of QString instances perhaps rather falls into the small and isolated use case that doesn’t translate very well into real applications.
I disagree that tst_qsettings isn't a real-world application. Most Qt
applications will have a part that does serialisation into one of JSON,
QSettings, or XML, and checking the impact of QString -> QAnyStringView
on a test that does makes perfect sense to me to gauge the impact on
that part of the API. Granted, it's a maximum-attainable savings gauge.
But it's one of the better indications we have, apart from looking at
the assembly generated, on how QAnyStringView affects codegen.
That said, there are also Qt apps that don't use tr() and just pass
string literals for human-readable text. Those would get a similar
reduction in executable code size if _all_ QString setters were replaced
by QAnyStringView ones.
The file APIs also suffer from the forced use of UTF-16 for paths (cf.
https://bugreports.qt.io/browse/QTBUG-104095). Hands up: who has in the
past been lazy and said "meh, QFile::encodeName(), I'll just skip that" 🖐
> There are most certainly classes where it’d be good if we could replace that implementation with e.g. a std::pmr::vector with an optimised allocator. And then being stuck with a QList API forces both us and client code to construct suboptimal data structures. And there are APIs where replacing the QString version with QAnyStringView makes perfect sense (such as all remaining fromString factory functions).
> But that we either replace all, or none of our APIs with something taking a view or a span are perhaps not the only outcomes of this conversation.
https://bugreports.qt.io/browse/QTBUG-101388 explicitly proposes to
start where there's the most bang for the buck, and I've been following
it to the letter.
> Can we focus on the cases with the biggest wins, like you already did with QRegion, QSettings, and QObject::setObjectName? What APIs in Qt that take a QString are usually called with a string literal in real applications, rather than with an already created QString object (that is in turn the result of user input or reading from some storage)?
Exactly what https://bugreports.qt.io/browse/QTBUG-101388 proposes.
> What was the outcome of the QObject::setObjectName change for e.g. Qt Creator?
I don't have numbers for QtC, but I have numbers for uic-generated code:
That's not separated from the rest of the code, so I take it fits the
real-world benchmark better: In particular those 1.7% are _just_
setObjectName(). Just in uic-generated code. 1.7% of executable code
previously wasted on temporary QString creation in a real-life library.
And the simplest code is also the most efficient:
The sad fact is that this is just rolling back the inefficiencies caused
by making objectName a QString in Qt 4.
> What would a QSpan-returning implementation of e.g. QObject::findChildren or QItemSelectionModel::selectedIndexes look like? Is that even feasible without using coroutines?
It's not possible. As per my previous emails, a span can only be used to
return stored contiguous data. Returning computed or non-contiguous data
requires a co-routine (or callbacks) (NOIv1 vs NOIv2).
Marc Mutz <marc.mutz at qt.io>
Principal Software Engineer
The Qt Company
Erich-Thilo-Str. 10 12489
Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin,
Registergericht: Amtsgericht Charlottenburg,
HRB 144331 B
More information about the Development