[Interest] Building strings with .arg() (arrrgh)

Constantin Makshin cmakshin at gmail.com
Fri Mar 6 07:22:31 CET 2020


Every `arg(numeric_value)` overload uses a temporary `QString` object to build a text representation of `numeric_value` needed by the actual placeholder-replacement function. Even `arg(QChar)` and `arg(char)` create single-character `QString`s and pass them to either `arg(const QString&)` or `arg(QStringView)`. So, unless localized placeholders are used, all `arg(numeric_value)` overloads are exactly equivalent to `arg(QString::number())`.

The obvious performance-wise advantage of "multiArg" is that it needs to parse the format string and allocate the result only once instead of doing that over and over for each `arg()` call.

On 03/03/2020 09:16 AM, Max Paperno wrote:
> 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 at qt-project.org
> https://lists.qt-project.org/listinfo/interest

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20200306/8d02b408/attachment.sig>


More information about the Interest mailing list