Well, not sure if my question was too vague, TL;DR, or just no one knows/cares to explain. So I created some benchmarks. Code and my results at:

https://gist.github.com/mpaperno/e09d1c295eef94a45176c5cb2002a00e

QStringLiteral().arg and .append() is consistently a little faster than QString() versions, though certainly not by much. QLatin1String().arg() and QStringView().arg() sit right about in between them (but are Qt 5.14+ only, and undocumented). The winner for raw speed is QStringBuilder (string % string % ..., or the "+" equivalent with QT_USE_QSTRINGBUILDER). For brevity it is certainly QString::asprintf() especially if padding/formatting is needed.

Another thing I learned is that .arg(numeric_value) doesn't really ever do better than .arg(QString::number()), especially when it can be combined into one .arg() with other strings. Even if one wants to pad the numbers, eg. QString::number(intVal, 16).rightJustified(4, QChar('0')), it is still faster than the .arg() equivalent. Though certainly more verbose.

Oh and QString.append(QLatin1String()) seems no faster than append(QStringLiteral()), despite what the Qt docs seem to suggest. I wasn't measuring memory usage per se, just overall speed.

If anyone sees any issues or naiveté with my benchmarks I'd love to hear about it. I played with a lot of minor variations which didn't deserve their own separate tests, but made some notes in the code comments. Obviously there are almost limitless variations which I didn't cover, and my focus was mainly on plain Latin1 strings.

Cheers,
-Max


On 2/16/2020 11:33 PM, Max Paperno wrote:
HI folks,

I'm confused about a "best" way to use .arg() with fixed/static strings (not tr()). Or if it should be used at all, for that matter, in terms of efficiency.

QStringLiteral seemed pretty good to me after reading several blog posts
(from Marc Mutz, Kai Koehne, Olivier Goffart, among others), all of which are mentioned on Qtforum post [Create QString with QStringLiteral and arg][1] along with some opinions.

Then found the [HEADS-UP: QStringLiteral][2] post by Marc on the development list and didn't feel so good about it anymore. Specifically where he says that using it with .arg() is an "anti-pattern" but not in any way that I can understand (vs. just using QString). I went through that whole meandering thread but didn't see string builder stuff brought up again.

It also mentions (and I found other references) that QStringView and QLatin1String have .arg() methods, albeit w/out number formatting. Which I can see in the code, but aren't documented anywhere AFAICT. Nor can I find when these methods became available. I'm hesitant to use undocumented methods (though it wouldn't be the first time) and would prefer to maintain as much compatibility with older Qt versions as possible/reasonable. More importantly, I have no idea what doing something like QLatin1String("foo %1").arg(myQstring) would even mean.

OTOH I found a number of code examples here and there (including KDE code, like Konsole) where people specifically changed QString("%1").arg() calls to use QStringLiteral instead.

Also I'm not clear if using QStringLiteral with + (or %) operators is also an "anti-pattern"... I understand the methods like append() can make more efficient use of QLatin1String, but does a plain quote-wrapped char literal get implicitly converted to QString when used e.g. like:

"Value of " + myQstring + " is: " + QString::number(x);

Would it be more efficient to wrap those literals in a QStringLiteral, QLatin1String, QStringView (or u""), or just leave them bare?

Realizing that "best" is subjective, and thinking of a specific project I'm working on, my goals, in order of importance, are, roughly:

1) Stability; 2) Minimal CPU time (fast, some of this could be used within animations and such); 3) Runtime memory use; 4) Clean code; 5) Size of produced binary.

In many cases I'm just building strings for error/warning/status messages (but not QDebug streams, although they may end up as debug output eventually, or never be seen at all). And these don't, or shouldn't, happen very often at runtime. But in some cases the stings will be used internally by other code. In most (if not all) cases I don't care about UTF encoding, plain ASCII/L1 is fine.  But there are often numerical types involved which need to be converted to strings somehow. And other strings to be inserted (with .arg()) are often QStrings (from Qt lib code or whatever). The built strings are typically passed on to other functions (as const QString &) for further processing or possible display to the user/downstream developer.

What's a programmer to do?  Does it even matter? Is there a faster way to build strings (within reason... yes I could just use C-level code but let's not get carried away).

Thanks!
-Max


[1]: https://forum.qt.io/topic/86964/create-qstring-with-qstringliteral-and-arg/8 [2]: https://lists.qt-project.org/pipermail/development/2019-August/037145.html


_______________________________________________
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest

Reply via email to