在Qt中没有分配的情况下将(多个!)数字转换为字符串的正确方法

时间:2014-05-03 11:56:13

标签: c++ performance qt qstring itoa

TL;博士

我想每秒多次致电QString::number(int)。它非常慢:似乎每次都分配一个新的字符串。试图在相同的字符串上使用setNum,但仍然没有快乐。


原创,长期问题:

问题

我有一大堆数字(例如整数),我想将它们格式化为文本,然后(可能不会立即)写入文件。朴素的方式看起来大概是 1

QString allData;
foreach(const int & value, values) {
    allData += QString::number(value);
    allData += '\n';
}

我机器上的 150000 整数需要 280ms ,这对我来说似乎很重要。我想这是因为QString::number被调用150000次并且每次都分配新的字符串。当我尝试使用itoa(不分配内存)时,这被证实是问题的根源。

可能但不是Qt [not-cute]解决方案

QString allData;
char buffer[100];                               // <-------
foreach(const int & value, values) {
    _itoa_s(value, buffer, sizeof(buffer), 10); // <-------
    allData += buffer;
    allData += '\n';
}

对于相同的 150000 整数(约 4x 更快),这需要 70ms ,这对我来说是可接受的(I我认为我也可以使用字符串连接做一些事情,但是让我们把它留在这个问题之外)

但是我不喜欢我必须使用一些不标准的,可能已弃用的,可能不可移植的 2 函数(并不是说这看起来很难看)。< / p>

然后我记得还有一个实例方法:QString::setNum。我希望我可以使用与itoa相同的模式:只分配一个字符串并每次修改它。

理想,但无效解决方案

QString allData;
QString number;                       // <-------
foreach(const int & value, values) {
    number.setNum(value);             // <-------
    allData += number;
    allData += '\n';
}

不幸的是,这与QString::number没有太大的区别:大约280毫秒,好吧,可能 250毫秒但仍然太多。

所以,恭喜你到达这里:)最后......

问题

  1. 什么 Qt专家建议我?关闭并使用itoa,尽管在其他芳香的C ++ / Qt代码中有明显的C气味?
  2. 或者我能以某种方式说“来吧,Qstring,只是把这个号码给你”
  3. 我想知道为什么setNum没有做到这一点

  4. 脚注:

    1 在实际代码中,我不仅有150000个整数,还有50000个整数三元组,我还在它们之间添加'\t'。这是我实际代码的唯一区别,我想这并不重要:这里我只对QString::number vs itoa的表现感兴趣。

    2 实际上,我很惊讶MinGW也有_itoa_s的行为就像Visual Studio一样,但我仍然有一些尴尬的感觉,在我的抛光Qt中使用这么脏的功能代码降低了它的可移植性。如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:5)

您可以尝试使用共享相同QString接口的QByteArray,但更适合性能问题。使用此代码,我获得36 ms(qt 5.2 clang)与原始57 ms(在我的机器上):

QByteArray allDatab;
foreach(const int & value, values) {
    allDatab += QByteArray::number(value);
    allDatab += '\n';
}
QString result(allDatab);
这个版本

和29毫秒(可能确认你对setNum的假设):

QByteArray allDatad;
QByteArray number;                       
foreach(const int & value, values) {
    number.setNum(value);             
    allDatad += number;
    allDatad += '\n';
}

答案 1 :(得分:3)

如何使用STL?

我测试了你的代码(修改循环以简化)

int main() {
  stringstream ss;
  for(int i=0; i<2000000; ++i) {
     ss << i << "\n";
  }
}

我获得了

time ./ss_test
  real  0m0.146s
  user  0m0.139s
  sys   0m0.006s

使用Qt版本(在我的机器中)

int main() {
  QString allData;
  for(int i=0; i<2000000; ++i) {
    allData += QString::number(i);
    allData += '\n';
  }
}

我获得了

time ./qtstring_test 
   real 0m0.516s
   user 0m0.508s
   sys  0m0.008s