[Development] QtCS 2017 QtCore sessions

Marc Mutz marc.mutz at kdab.com
Fri Dec 1 20:57:33 CET 2017


On 2017-12-01 19:26, Thiago Macieira wrote:
> On Friday, 1 December 2017 01:31:18 PST Marc Mutz wrote:
>> > Once those operator<=> are there, what benefit is there in having the
>> > API
>> > public and documented?
>> 
>> The spaceship operator solves the problem for qCompareStrings(). One
>> could say we already have all relational operators for all 
>> combinations
>> of string-like objects to solve it for the user _now_, but
>> qCompareStrings(), like operator<=>() return the full information, 
>> while
>> relational operators only return a subset. You know that, I know. I'm
>> just mentioning it for completeness sake.
> 
> Ok, so your case is when you have two string-like objects and you want 
> to get
> the ordering result. Since we don't yet have the spaceship operator, 
> you have
> to call the compare() function. But you can't do that in clean, generic 
> code
> because you don't know if the first argument is an actual QString or
> QStringView, or if it's just a char16_t literal.
> 
> Is that it?
> 
> Why can't they write
> 
> 	QStringView(s1).compare(s2) ?

I think you owe me a bit more thought on an answer to a mail of mine 
that that :P
A quick look at the qCompareString() overload set will answer this 
question (hint: the lhs is not always QStringView).

>> Ah, but you said that the flaw was in the _standard_. But what you 
>> show
>> are sub-optimal compiler implementations. There's nothing in the
>> standard that prevents a compiler to implement char_traits::length() 
>> as
>> a compiler intrinsic that can have different backends for constexpr 
>> and
>> runtime evaluation.
> 
> The flaw is in the standard because it does not allow me to implement 
> an
> optimised version using whichever tools I want to.

The standard is not obliged to publicly give you all the plumbing to 
re-implement the standard library. The lack of plumbing is _sometimes_ a 
flaw in the standard, yes (std::invoke), but not always. You are 
supposed to use the standard library functionality, not re-implement it. 
In this case, the interface is char_traits::length, it exists on all 
supported platforms and does what we'd like it to do, incl., from C++17 
on, constexpr.

>> So, would the following be acceptable:
>> 
>> 1. QSV uses char_traits<char16_t>::length() to calculate the length
>> (that was my initial implementation, but it's constexpr only starting
>> with C++17). Then QSV(Char*) is only constexpr in C++17. I can live 
>> with
>> that.
> 
> No, because...
> 
>> 2. You/Intel work on the compiler vendors to get
>> char_traits<char16_t>::length() implemented as an intrinsic, with SIMD
>> at runtime and compiler magic at compile-time?
> 
> We should do that anyway, but depending on it means we'll have 
> performance in
> 2021 or later (just look at how we have to build Linux binaries with 
> GCC 4.8).

Since char_traits::length would be called from inline code in QSV, its 
performance does not depend on how Qt was compiled, but on what the 
user's compiler is capable of. Also, presumably, the compiler was 
already optimizing char_traits::length() back when it wasn't constexpr 
(in C++11+14) and now has to implement something to not regress on 
runtime performance while still meeting constexpr restrictions. If it 
doesn't, then it's not our problem. It's SEP. And that is good. Pick 
your battles.

> The flaw exists today. My choice for fixing it is to sacrifice the part 
> we
> don't really need: the constexprness.

Fixing it in Qt is limiting both Qt and the standard library. Don't do 
that.

<rant>
The same is true, btw, of QMutex. Qt takes pride in how QMutex is faster 
than std::mutex. I think it's a shame. It shows that you didn't go the 
next step and get std::mutex fixed. Having QMutex not use std::mutex 
means that tsan doesn't work correctly, for one. Here, too, the "easy" 
local "fix" is to the detriment of both the standard library 
(slower-than-necessary mutex operations) and Qt (failure to work with 
tsan).

This habit of cocooning might have worked out ok when Qt was years ahead 
of the C++ standard library. But since those times in the 2000s, C++ has 
overtaken Qt in all aspects the committee decided to take on. Qt will 
have to adapt to this new reality or degrade to insignificance. Ride the 
wave or drown.

As I said elsewhere: innovate, don't replicate. See the bigger picture 
here: Where are the patches that integrate Qt's event system and 
signal/slots mechanism with Coroutines, to name just one? Instead you 
celebrate the perceived failures of the standard and Qt's ability to 
"fix" them by writing a SIMD strlen or take the null state of a Qt value 
class to optimize QOptional size.

This pattern repeats and repeats. V8 fork, anyone? When will Qt 
_finally_ learn? :) I said in my talks about QStringView that it's 
existential for Qt to get off its own container classes. I shall in the 
future extend that statement to anything that overlaps with std.

I explicitly do not exclude QString here, even though it's exempt for 
the time being. But people _do_ talk about a std::text_view, and it 
_will_ support utf8 strings and that, in combination, _will_ degrade 
QString to insignificance.

When Coroutines and ASIO land in C++, C++ will magically gain a 
cross-platform event loop. And more likely than not, you will have to 
integrate with it using Coroutines, futures and other awaitables, not 
the classic way of QAbstractEventDispatcher. It does not take a leap of 
imagination to assume that Coroutines TS will spark a ton of reactive 
GUI libraries for C++, incl. cross-platform ones. Qt needs to be 
prepared for that day. And the only way to prepare is to start working 
on innovative stuff and work with its various upstreams more, incl. the 
standard committee, and innovate. Stop. Fixing. Stuff. Locally. Get. 
Involved. Don't. Kodak. Qt.
</rant>

>> Then we fix the problem where it should be fixed, and just piggy-back 
>> on
>> the more general solution. And it's easy to sell to QSV users why that
>> ctor is not constexpr until C++17 (and we don't even need any 
>> #ifdefery
>> in the implementation).
>> 
>> What do you think?
> 
> We should fix the standard and we should help fix the implementations. 
> But I'm
> not accepting a performance drawback for 3 or more years until then.

Pick your battles. I offered a compromise. I think it's a good one. And 
I think you're seriously overestimating the effect of your change. Not 
because it doesn't give a large performance boost, when exercised (I'm 
sure it does), but simply due to the fact that that code will be 
exercised very rarely. And, when actually exercised, the smaller i-cache 
footprint of "my" function might just beat "your" high-performance 
function in wall-clock time. Yes, in a library, every missed 
optimisation is some user's performance bottleneck. But we have an easy 
solution for that: people should be able to find in the ctor's 
documentation the recommendation to use qustrlen() manually.

Thanks,
Marc




More information about the Development mailing list