我的 C++11 测试表明 sort(vector<string>) 比 C++03 还要慢,有什么错误吗?

My C++11 test show that sort(vector<string>) is even slower than C++03, any error?

有了正确的值引用和移动语义,C++11 的 swap/sort 速度应该等于或大于 C++03。所以我设计了一个简单的实验来测试这个。

我用-O2编译并运行它,用c++03和c++11标准。

$g++ test.cpp -O2 && ./a.out
10240000 end construction
sort 10240000 spent1.40035

$g++ test.cpp -O2 -std=c++11 && ./a.out
10240000 end construction
sort 10240000 spent2.25684

所以看起来启用了 C++11,程序变慢了。 我在一个非常新的 mac 和 gcc 环境中:

$gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

下面是源代码:

#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
    const size_t scale=600;
    char ret[scale];
    for(size_t i=0;i<scale;++i)
    {
        double rand0to1=(double)rand()/RAND_MAX;
        ret[i]=(char)rand0to1*92+33;
    }
    return ret;
}
int main()
{
    srand(time(NULL));
    const size_t scale=10240000;
    vector<string> vs;
    vs.reserve(scale);
    for(size_t i=0;i<scale;++i)
    {
        vs.push_back(randomString());
    }
    cout<<vs.size()<<" end construction\n";
    clock_t begin=clock();
    sort(vs.begin(),vs.end());
    clock_t end=clock();
    double duration=(double)(end-begin)/CLOCKS_PER_SEC;
    cout<<"sort "<<scale<<" spent"<<duration<<"\n";
    return 0;
}

我的程序或理解有任何错误,如何解释我的测试结果?

真的需要你的专业知识!

您的测试代码有几个问题。

  1. 您在 ret 中生成的字符串未以 null 结尾,因此它将包含堆栈中的垃圾,这可能会随着编译器设置而改变。这是导致您出现奇怪结果的最可能原因:c++11 版本对较长的字符串进行排序。

  2. 您的转换导致字符串完全相同。这不是测量的实际问题,但可能不是您对测试感兴趣的问题。

  3. 您不应使用真正随机的种子进行基准测试。您希望在每个 运行 获得可再现性时生成相同的字符串。

此固定版本代码:

#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
    const size_t scale=600;
    char ret[scale];
    for(size_t i=0;i<scale;++i)
    {
        double rand0to1=(double)rand()/RAND_MAX;
        ret[i]=(char)(rand0to1*92+33);
    }
    ret[scale-1] = 0;
    return ret;
}
int main()
{
    srand(1);
    const size_t scale=10240000;
    vector<string> vs;
    vs.reserve(scale);
    for(size_t i=0;i<scale;++i)
    {
        vs.push_back(randomString());
    }
    cout<<vs.size()<<" end construction\n";
    clock_t begin=clock();
    sort(vs.begin(),vs.end());
    clock_t end=clock();
    double duration=(double)(end-begin)/CLOCKS_PER_SEC;
    cout<<"sort "<<scale<<" spent "<<duration<<"\n";
    return 0;
}

产生了我相信你所期待的:

$ g++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.8765

$ g++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.72834

顺便说一句,mac 上 Xcode 的 g++ 实际上是 clang。但结果是相似的:

$ clang++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.9408

$ clang++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.33261

已使用 g++ 6.2.1 和 clang 3.9.0 进行测试。 -std=c++03 开关很重要,因为没有它,g++ 会以一种提供快速时间的模式编译。