C++ cout打印很慢

Ram*_*ter 7 c++ performance cout

我注意到如果我使用cout打印出长字符串(char*),它似乎一次打印1个字符到Windows 7,Vista和Linux(使用putty)的屏幕上,使用Windows上的Visual C++ 2008和Linux上的G ++.Printf是如此快得多,我实际上从cout切换到printf,用于我的项目中的大多数打印.这让我感到困惑,因为这个问题让我觉得我是唯一一个有这个问题的人.

我甚至写了一个cout替换,看起来像是在我的comp上击败cout的裤子 -

class rcout
{
public:
    char buff[4096];
    unsigned int size;
    unsigned int length;

    rcout()
    {
        size = 4096;
        length = 0;
        buff[0] = '\0';
    }

    ~rcout()
    {
        printf("%s", buff);
    }

    rcout &operator<<(char *b)
    {
        strncpy(buff+length, b, size-length);
        unsigned int i = strlen(b);
        if(i+length >= size)
        {
            buff[size-1] = '\0';
            printf("%s", buff);
            b += (size-length) -1;
            length = 0;
            return (*this) << b;
        }
        else
            length += i;
        return (*this);
    }

    rcout &operator<<(int i)
    {
        char b[32];
        _itoa_s(i, b, 10);
        return (*this)<<b;
    }

    rcout &operator<<(float f)
    {
        char b[32];
        sprintf_s(b, 32, "%f", f);
        return (*this)<<b;
    }
};

int main()
{
    char buff[65536];
    memset(buff, 0, 65536);

    for(int i=0;i<3000;i++)
        buff[i] = rand()%26 + 'A';

    rcout() << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
    Sleep(1000);
    cout << "\n\nOk, now cout....\n\n";
    cout << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
    Sleep(1000);
    cout << "\n\nOk, now me again....\n\n";
    rcout() << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
    Sleep(1000);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

任何想法为什么cout打印这么慢对我来说?

min*_*ang 12

注意:此实验结果对MSVC有效.在库的其他一些实现中,结果会有所不同.

printf 可能(更快)比cout.虽然printf在运行时解析格式字符串,但它需要的函数调用要少得多,实际上需要少量指令才能完成相同的工作cout.以下是我的实验总结:

静态指令的数量

一般来说,cout生成很多代码printf.假设我们有以下cout代码用一些格式打印出来.

os << setw(width) << dec << "0x" << hex << addr << ": " << rtnname <<
  ": " << srccode << "(" << dec << lineno << ")" << endl;
Run Code Online (Sandbox Code Playgroud)

在具有优化的VC++编译器上,它生成大约188字节的代码.但是,当您替换printf基于它的代码时,只需要42个字节.

动态执行指令的数量

静态指令的数量只是告诉静态二进制代码的区别.更重要的是在运行时动态执行的实际指令数.我也做了一个简单的实验:

测试代码:

int a = 1999;
char b = 'a';
unsigned int c = 4200000000;
long long int d = 987654321098765;
long long unsigned int e = 1234567890123456789;
float f = 3123.4578f;
double g = 3.141592654;

void Test1()
{
    cout 
        << "a:" << a << “\n”
        << "a:" << setfill('0') << setw(8) << a << “\n”
        << "b:" << b << “\n”
        << "c:" << c << “\n”
        << "d:" << d << “\n”
        << "e:" << e << “\n”
        << "f:" << setprecision(6) << f << “\n”
        << "g:" << setprecision(10) << g << endl;
}

void Test2()
{
    fprintf(stdout,
        "a:%d\n"
        "a:%08d\n"
        "b:%c\n"
        "c:%u\n"
        "d:%I64d\n"
        "e:%I64u\n"
        "f:%.2f\n"
        "g:%.9lf\n",
        a, a, b, c, d, e, f, g);
    fflush(stdout);
}

int main()
{
    DWORD A, B;
    DWORD start = GetTickCount();
    for (int i = 0; i < 10000; ++i)
        Test1();
    A = GetTickCount() - start;

    start = GetTickCount();
    for (int i = 0; i < 10000; ++i)
        Test2();
    B = GetTickCount() - start;

    cerr << A << endl;
    cerr << B << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是Test1(cout)的结果:

  • 执行指令:423,234,439

  • 内存负载/存储:约.320,000和980,000

  • 经过时间:52秒

那么,怎么样printf?这是Test2的结果:

  • 执行指令:164,800,800

  • 内存负载/存储:约.70,000和180,000

  • 经过时间:13秒

在这台机器和编译器中,printf速度要快得多cout.在两个执行指令的数量和加载/存储的数量(表示缓存未命中数)中有3~4倍的差异.

我知道这是一个极端的例子.此外,我应该注意到,cout当您处理32/64位数据并且需要32/64平台独立性时,这会容易得多.总是有权衡.我cout在检查类型时使用非常棘手.

好的,cout在MSVS中糟透了:)

  • 答案选择"好吧,在MSVS的cout只是糟透了:)",你是对的,这就是问题所在 (4认同)
  • 现在,我们得到了Microsoft Connect的答案 - "这是我们的C和C++标准库实现如何设计的一个不幸结果".请参见http://connect.microsoft.com/VisualStudio/feedback/details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance-bug-in-c-library (3认同)

Cha*_*via 9

我建议你在另一台计算机上尝试相同的测试.对于为什么会发生这种情况,我没有一个好的答案; 我只能说我从来没有注意到cout和printf之间的速度差异.我还在Linux上使用gcc 4.3.2测试了你的代码,并没有任何区别.

话虽这么说,你不能轻易地用你自己的实现替换cout.事实上,cout是std :: ostream的一个实例,它内置了很多功能,这对于与iostream运算符重载的其他类的互操作性是必需的.

编辑:

任何人说printf总是快于std::cout根本就是错误的. 我刚刚运行了minjang发布的测试代码,gcc 4.3.2和64位AMD Athlon X2上的-O2标志,cout实际上更快.

我得到了以下结果:

printf: 00:00:12.024
cout:   00:00:04.144
Run Code Online (Sandbox Code Playgroud)

cout总是比printf快吗?可能不是.尤其不适用于较旧的实现.但是在较新的实现上,iostream可能比stdio更快,因为编译器在编译时不知道需要调用哪些函数才能将整数/浮点数/对象转换为字符串.

但更重要的是,printf与cout的速度取决于实现,因此OP描述的问题不容易解释.