【问题标题】:Why is the performance varies different when concatenating many strings?为什么连接多个字符串时性能会有所不同?
【发布时间】:2016-04-01 14:45:55
【问题描述】:

我很好奇连接多个字符串的性能。在阅读Efficient string concatenation in C++ 之后,我做了一些测试。但是不同编译器的结果是不同的。

这是我的代码。 (代码中的定时器来自here。)

#include <iostream>
#include <sstream>
#include <string>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure {
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F&& func, Args&&... args) {
        auto start = std::chrono::system_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT>
            (std::chrono::system_clock::now() - start);
        return duration.count();
    }
};

std::string strAppend(const std::string &s, int cnt) {
    std::string str;
    for (int i = 0; i < cnt; ++i)
        str.append(s);
    return str;
}

std::string strOp(const std::string &s, int cnt) {
    std::string str;
    for (int i = 0; i < cnt; ++i)
        str += s;
    return str;
}

std::string strStream(const std::string &s, int cnt) {
    std::ostringstream oss;
    for (int i = 0; i < cnt; ++i)
        oss << s;
    return oss.str();
}

std::string strReserveAndOp(const std::string &s, int cnt) {
    std::string str;
    str.reserve(s.size() * cnt);
    for (int i = 0; i < cnt; ++i)
        str += s;
    return str;
}

std::string strReserveAndAppend(const std::string &s, int cnt) {
    std::string str;
    str.reserve(s.size() * cnt);
    for (int i = 0; i < cnt; ++i)
        str.append(s);
    return str;
}

int main() {
    const std::string s("Hello world!");
    const int cnt = 1000000 * 5;
    std::cout << "ostringstream: " << measure<>::execution(strStream, s, cnt) << "ms" << std::endl;
    std::cout << "+= operator: " << measure<>::execution(strOp, s, cnt) << "ms" << std::endl;
    std::cout << "s.Append(): " << measure<>::execution(strAppend, s, cnt) << "ms" << std::endl;
    std::cout << "s.Reserve() & +=: " << measure<>::execution(strReserveAndOp, s, cnt) << "ms" << std::endl;
    std::cout << "s.Reserve() & s.Append(): " << measure<>::execution(strReserveAndAppend, s, cnt) << "ms" << std::endl;
}

使用 GCC 5.1 在 Ideone 上测试得出结果:

ostringstream: 602ms
+= operator: 345ms
s.Append(): 336ms
s.Reserve() & +=: 224ms
s.Reserve() & s.Append(): 225ms

其中ostringstream 最慢,reserve() 稍快。

但是在 Visual Studio 2015 社区上运行相同的代码时,结果如下:

ostringstream: 4413ms
+= operator: 9319ms
s.Append(): 8937ms
s.Reserve() & +=: 8966ms
s.Reserve() & s.Append(): 8815ms

注意相对速度,ostringstream 最快,reserve() 似乎没有加速。

那为什么会这样呢?编译器优化还是其他?

【问题讨论】:

  • 你是怎么用VS编译的? /O2 发布?
  • @JameyD 感谢您指出这一点。我用/OdXD
  • libc++ 也是一个有趣的案例,使用 ostringstream 似乎更慢,但使用 append 更快(与 reserve+append 相同)。
  • -1 是另一个速度问题,包含调试构建时间。每个分析/速度问题都被问到......但我们仍然会遇到调试构建时间问题。

标签: c++ performance c++11


【解决方案1】:

感谢Jamey D。看来我的猜测是对的。将优化从/Od 更改为/O2。结果是:

ostringstream: 1098ms
+= operator: 362ms
s.Append(): 356ms
s.Reserve() & +=: 216ms
s.Reserve() & s.Append(): 227ms

这与 GCC 5.1 相同。

【讨论】:

  • 我想这就是我的问题的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2019-12-29
相关资源
最近更新 更多