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

Max Paperno max-l at wdg.us
Tue Mar 3 07:16:49 CET 2020


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




More information about the Interest mailing list