QString::number(int)
many times per second. It is very slow: seems like it allocates a new string each time. Tried to use setNum
on same string instead, still no joy.Original, long question:
I have a big array of numbers (say, integers) and I want to format them into text, that will be then (maybe not immediately) written to file. Naive way looks approximately1 like this:
QString allData;
foreach(const int & value, values) {
allData += QString::number(value);
allData += '\n';
}
It takes about 280ms for 150000 integers on my machine which seems to much for me. I suppose that this is because QString::number
is called 150000 times and each time allocates new string. This is someway confirmed to be the root of the problem when I try to use itoa
(which does not allocate memory) instead.
[not-cute]
solutionQString allData;
char buffer[100]; // <-------
foreach(const int & value, values) {
_itoa_s(value, buffer, sizeof(buffer), 10); // <-------
allData += buffer;
allData += '\n';
}
This takes about 70ms for the same 150000 integers (about 4x faster) which is by now acceptable for me (I think I can do something with string concatenation as well, but let's leave this outside this question)
But I don't like that I have to use some unstandard, probably deprecated, probably unportable2 function (not to say that this just looks ugly).
Then I remembered that there is also an instance method: QString::setNum
. I hoped I could use the same pattern as with itoa
: have only one string allocated and modify it each time.
QString allData;
QString number; // <-------
foreach(const int & value, values) {
number.setNum(value); // <-------
allData += number;
allData += '\n';
}
Unfortunately, this doesn't make big difference from QString::number
: again about 280ms, well, maybe 250ms but still too much.
So, congrats if you reached here :) and finally...
itoa
despite the distinct smell of C in otherwise fragrant C++/Qt code?setNum
did not do the trick?Footnotes:
1 In actual code i have not just 150000 integers, but 50000 triples of integers which I also add '\t'
between them. This is the only difference from my actual code and I guess it is not important: here I'm interested only in performance of QString::number
vs itoa
.
2 Actually, I was surprised that MinGW also has _itoa_s
that behaves just like as Visual Studio's, but I still have some awkward feeling that using such a dirty function in my polished Qt code reduces its portability. Correct me if I'm wrong.
You can try with QByteArray that shares same QString's interface but is more suitable for performance issues.I obtain 36 ms (qt 5.2 clang) vs. your original 57 ms (on my machine) with this code:
QByteArray allDatab;
foreach(const int & value, values) {
allDatab += QByteArray::number(value);
allDatab += '\n';
}
QString result(allDatab);
and 29 ms with this version (that maybe confirm your assumptions about setNum):
QByteArray allDatad;
QByteArray number;
foreach(const int & value, values) {
number.setNum(value);
allDatad += number;
allDatad += '\n';
}
How about using STL?
I tested your code (modifying the loop to simplify)
int main() {
stringstream ss;
for(int i=0; i<2000000; ++i) {
ss << i << "\n";
}
}
And I obtain
time ./ss_test
real 0m0.146s
user 0m0.139s
sys 0m0.006s
With Qt version (in my machine)
int main() {
QString allData;
for(int i=0; i<2000000; ++i) {
allData += QString::number(i);
allData += '\n';
}
}
I obtain
time ./qtstring_test
real 0m0.516s
user 0m0.508s
sys 0m0.008s
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With