[Development] Deprecation/removal model going into Qt 6

Giuseppe D'Angelo giuseppe.dangelo at kdab.com
Mon Jun 3 15:26:36 CEST 2019


Il 03/06/19 13:34, Kevin Kofler ha scritto:
> Giuseppe D'Angelo via Development wrote:
> 
>> Il 03/06/19 00:08, Kevin Kofler ha scritto:
>>> What you call "obsolete functionality" is functionality that existing
>>> code relies on and rightfully expects to remain there.
>>
>> Rightfully? By what right exactly?
> 
> APIs in libraries are meant to be used. I consider it an entirely reasonable
> expectation by developers using the APIs that they will not be removed under
> them because the library developers consider them "obsolete". Imagine the
> chaos if Intel or AMD decided to remove some random "obsolete" x86
> instructions from their CPUs! x86 has kept backwards compatibility with
> every single instruction for more than 30 years. This is the standard
> software libraries should be held to, too.

Nice try: https://rationalwiki.org/wiki/Straw_man#Forms

Specifically: moving the focus from a GUI framework's API to a 
foundational computer architecture design (which must provide much 
stronger guarantees).


Also, please name me 3 GUI frameworks that have not broken APIs for 30 
years.

Also also, please name me 3 libraries that have not broken APIs for the 
30 years.

Also also also, at least in the x86-64 world, major "API breaks" at the 
assembly level have already somehow occurred. And that's an architecture 
that has been around for less than 20 years.



>>> I'd rather get fewer (or even no) new features than losing existing ones.
>>
>> How is this even an argument? Qt will need to evolve and acquire
>> features to remain competitive. Again, development bandwidth is finite:
>> either the overall quality decreases or some things have to get dropped.
> 
> Qt has long reached a point where it can be considered complete. Its main
> selling point is portability to many different platforms rather than some
> specific feature. Additional features don't necessarily need to be in the
> main Qt library, but can be in community-developed addons such as KDE
> Frameworks or such as the many third-party Qt-based Free Software libraries
> out there. (They can also be in Qt-Company-developed Qt Solutions if there
> is manpower left for that.)
> 
> Qt has also become larger and larger over time (despite the removal of APIs
> considered obsolete). 

The removal of APIs in Qt 5 lifetime has been mostly "limited" to 
dropping entire obsolete modules. No cleanup has been done to deprecated 
API inside a module. Qt 6 wants to do that, and the point of this thread 
is how to minimize the pain.



> Just compare the size of the Qt 3 tarball with the
> size of the Qt 5 monolithic tarball. This is not the result of keeping old
> APIs around, but of feature creep.

"Creep" is questionable; and anyhow off-topic.


> So I disagree with the assertion that Qt needs more features to remain
> competitive.

And I disagree with this. And even assuming to stop adding new feature,s 
the _current_ feature set may need refactoring and redesigns, which may 
mean API breaks.



>>> See also Boudewijn Rempt's blog post on the subject:
>>> https://valdyas.org/fading/hacking/happy-porting/
>>
>> I agree with the principle (API breaks are painful), but I strongly
>> disagree with the idea that no API breaks can ever possibly happen. And
>> the specific example is a terrible one to make a point as the resulting
>> API break is trivial to work around (I defined such breakages
>> "scriptable").
> 
> The Q_FOREACH to ranged for change is not as easy to port to as people
> think, because there are at least 2 pitfalls when porting to ranged for:
> 1. you have to add qAsConst or equivalent or you will be deep-copying your
>     implicitly-shared CoW container,
> 2. code that was changing the container during the iteration, which worked
>     just fine with Q_FOREACH (because the iteration would still be over the
>     original unchanged container), will now crash without warning. Even
>     qAsConst will not help you get a warning or error for it, because it only
>     constifies the reference for the ranged for itself and not for the code
>     within it.
> 
> This is effectively deprecating a safe construct for an unsafe one.

This is not the intended port, because it's not scriptable. Moving to a 
range-based for is the long-term solution, but that requires checking 
all usages.

The intended _scriptable_ solution is

1) copy and paste Q_FOREACH from qglobal.h into a central header of your 
project
2) rename all occurrences it to MY_FOREACH
3) done

What's the difference, then? For your code, minimal (just use another 
macro). But for Qt, that it stops supporting Q_FOREACH, teaching its 
usage, and advocating for it.



>>> An array of pointers is the most efficient data structure in practice
>>> (operations are at most O(n)), dropping it in favor of an O(mn) data
>>> structure (where m = sizeof(T)) such as QVector is a pessimization. And
>>> QList also has the prepend optimization that makes most prepends even
>>> O(1) rather than O(n). I don't see why almost everybody hates it.
>>
>> As written, the above makes no sense, as it looks like you're comparing
>> apples and oranges: time complexities against space complexities.
> 
> I'm speaking exclusively of time complexities. The space only matters when
> it goes into the formula for the time, which is the case for QVector.
> 
> QList::insert and QList::removeAt have O(n) time complexity.
> QVector::insert and QVector::removeAt have O(mn) time complexity.
> 
> QList::prepend has O(1) amortized and O(n) worst case time complexity.
> QVector::prepend has O(mn) (always!) time complexity.
> 
> If you are dealing with a large class or struct, e.g. 800 bytes, then the
> QVector operations are 100 times slower than the QList ones!

This is just *false*. You're (deliberately?) ignoring the cost of memory 
allocations and deallocations, hiding them in big-O constants, something 
I already warned you about. I won't then waste time debunking this.

>>> For the "unnecessary" part, because Qt has been working fine without
>>> QString SSO for years.
>>
>> Nice try: https://en.wikipedia.org/wiki/Appeal_to_tradition
> 
> This is not an appeal to tradition, but to practical experience. QString is
> working well in thousands of software packages now. 

Another appeal to tradition.


> Of course, that doesn't
> imply that it is not possible to do better, in theory. But is this
> optimization worth the trouble of breaking the ABI? 

Yes.


(Keep in mind that my
> argument is that Qt 6 should either be source&binary-compatible with Qt 5

This won't happen.


>> Second, string classes in all major C++ libraries and frameworks are
>> deploying SSO *because* it is a performance win.
> 
> SSO is a clear performance win for std::string because std::string is NOT
> CoW (in fact, g++'s implementation used to be, but it was dropped because
> some obscure "clarification" in C++11 is interpreted as forbidding it).

The "obscure" clarification is called exception safety.


> So
> you have to deep-copy anyway, and SSO saves the allocation. But SSO bypasses
> CoW, so is only a win on the current architectures with ridiculously slow
> atomics and fast bulk copies. If atomics ever get optimized in a new CPU
> architecture, you'll wish the old QString back.

CoW and SSO are orthogonal optimizations. folly's fbstring has *both*.



>>> For the "probably also counterproductive" part:
>>> * Because there are surely architectures or environments where copying
>>> 256 bytes (or whatever the SSO max length actually is)
>>
>> This is a straw man argument, specifically an exaggeration.
>>
>> At some QtCS Thiago was talking about 23-24 QChars, i.e. 48 bytes, plus
>> a couple of pointers or so, to bring it to 64 bytes (~ a cacheline).
> 
> "or whatever the SSO max length actually is". So 64 bytes it is. Still 8
> times more than before. This is only faster because current architectures
> suck at atomics.

Hey, I somehow assumed that you liked the 30 years old compatible 
assembly? Guess what's the price to pay for being compatible with an 
overly-strict and expensive model for atomics?



>> This thread was about managing API breaks. Adding SSO to QString is not
>> meant to be an API break (*). Please stop derailing the thread.
>>
>> (*) Emphasis on _meant_, because obviously it yields observable side
>> effects.
> 
> This thread was also about managing ABI breaks, which QString SSO definitely
> is.

Qt 6 will break ABI.

This thread is about API breaks. I should know, I've started it.


-- 
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4329 bytes
Desc: Firma crittografica S/MIME
URL: <http://lists.qt-project.org/pipermail/development/attachments/20190603/5880cb84/attachment-0001.bin>


More information about the Development mailing list