[Development] How qAsConst and qExchange lead to qNN

Marc Mutz marc.mutz at qt.io
Mon Nov 14 18:30:54 CET 2022


Hi Ulf,

On 14.11.22 17:37, Ulf Hermann via Development wrote:
> Hi Marc,
> 
>> On 11.11.22 09:35, Ulf Hermann via Development wrote:
>>> There is an undeniable benefit of _offering_ QSpan, QStringView, and
>>> generator APIs in a few relevant cases:
>>>
>>> 1. Users want to pass a "foreign" container to a Qt function that
>>> doesn't only store it as QList or QString. It might merely iterate it or
>>> store it as something else.
>>
>> The assumption that there's a problem only for "foreign containers" is
>> incorrect: Take the native Qt container QString as an example. See
>> assembly in my QAnyStringView blog post:
>> https://www.qt.io/blog/qstringview-diaries-qanystringview You have this
>> problem as soon as you pass constant data, which is a common enough
>> use-case to warrant optimizing for.
> 
> My point is the "doesn't only store it as QList or QString" and 
> "foreign" is in quotes quite on purpose. Maybe that wasn't clear enough, 
> though.
> 
> So, if the method immediately converts whatever it gets to QList or 
> QString, then there is no point in passing it a span or view.

My point is that there _is_. Citing my blog post:

   callConsumeQStringHelloWorld():
         pushq   %rbp
         movl    $12, %esi
         leaq    .LC76(%rip), %rdx
         subq    $32, %rsp
         movq    %rsp, %rbp
         movq    %rbp, %rdi
         call    QString::fromUtf8(QByteArrayView)@PLT
         movq    %rbp, %rdi
         call    consumeQString(QString const&)@PLT
         movq    (%rsp), %rax
         testq   %rax, %rax
         je      .L834
         lock subl       $1, (%rax)
         je      .L839
   .L834:
         addq    $32, %rsp
         popq    %rbp
         ret
   .L839:
         movq    (%rsp), %rdi
         movl    $8, %edx
         movl    $2, %esi
         call    QArrayData::deallocate(QArrayData*, long long, long 
long)@PLT
         addq    $32, %rsp
         popq    %rbp
         ret

   callConsumeQStringViewHelloWorld():
         leaq    .L.str.3401(%rip), %rsi
         movl    $12, %edi
         jmp     consumeQStringView(QStringView)@PLT # TAILCALL


It matters whether the QString/QList creation is in front of or behind 
the ABI boundary. The size of the tst_qsettings executable for Clang 
builds went down by >10% when the API was switched over to 
QAnyStringView, without any changes to the test code itself (and 
QAnyStringView hasn't even got the size/tag swap that Thiago pointed out 
and that would make it require less gargantuan immediate values):
https://codereview.qt-project.org/c/qt/qtbase/+/353688

Sure, the sequence of assembler instructions is the same, but improved 
code locality means it'll also execute a bit faster. Also, if we can 
condense user code by 10% without changes to their code, then some users 
may have an easier time right-sizing their embedded hardware, e.g.


Finally, to give you the very big picture: we have a duty to avoid 
inflicting such egregiously inefficient code on the world. This bloat 
needs to be stored: on disk, in RAM, in cache. At each of these levels, 
the extra storage causes some pJ extra energy use, billions of times 
over, causing corresponding CO2 emissions.

The German government has started dealing out the well-known "blue 
angel" certificates for software now. Customers will eventually demand 
our help in getting the energy use of their software down so they can be 
certified.

We can, of course, ostrich on. But Qt is in a unique position, as a C++ 
native UI framework, to assist users in meeting climate goals. Think 
about it: Would projects that prefer programmer productivity over 
resource use inflict C++ on their programmers? Won't such projects 
rather (continue to) use Java and HTML, shipping applications with a 
bundled chromium to run a few HTML/JS apps in GiBs of memory instead of 
MiBs (hello, MS Teams!)? To me, it sounds more logical that projects 
that inflict C++ on their developers would be those projects that need 
to meet resource usage goals (because of right-sizing of embedded 
hardware or because they want to get certified as energy-efficient). And 
all this talk about convenience trumping efficiency is going to raise 
eyebrows in such projects.

Let's make C++ easy to use, for sure. But, sorry, using spans isn't 
difficult. Don't confuse familiarity with simplicity.

Thanks,
Marc

-- 
Marc Mutz <marc.mutz at qt.io>
Principal Software Engineer

The Qt Company
Erich-Thilo-Str. 10 12489
Berlin, Germany
www.qt.io

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 mailing list