Printf более чем в 5 раз быстрее, чем std:: cout?

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>

int main(int argc, char* argv[])
{
    std::clock_t start;
    double duration;    

    std::cout << "Starting std::cout test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
    {
        std::cout << "Hello, World! (" << i << ")" << std::endl;
    }

    duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Ending std::cout test." << std::endl;
    std::cout << "Time taken: " << duration << std::endl;

    std::system("pause");

    std::cout << "Starting std::printf test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
    {
        std::printf("Hello, World! (%i)\n", i);
        std::fflush(stdout);
    }

    duration = (std::clock() - start) / (double) CLOCKS_PER_SEC;

    std::cout << "Ending std::printf test." << std::endl;
    std::cout << "Time taken: " << duration << std::endl;

    system("pause");

    return 0;
}

Теперь, вот время для первых пяти запусков:

  • std:: cout test: 1.125; printf test: 0.195 s
  • std:: cout test: 1.154; printf test: 0.230 s
  • std:: cout test: 1.142; printf test: 0.216 s
  • std:: cout test: 1.322; printf test: 0.221 s
  • std:: cout test: 1.108; printf test: 0.232 s

Как вы можете видеть, использование printf, а затем fflush ing занимает примерно в 5 раз меньше времени, чем при использовании std::cout.

Хотя я ожидал, что с помощью оператора std::cout << был бы, возможно, немного медленнее (почти минимальный), я не был готов к этой огромной разнице. Я делаю честный тест? Если да, то что делает первый тест намного медленнее второго, если они по сути делают то же самое?

Ответы

Ответ 1

Для сравнения настоящих яблок с яблоками повторите запись теста, так что единственное, что меняется между тестовыми примерами, - это используемая функция печати:

int main(int argc, char* argv[])
{
    const char* teststring = "Test output string\n";
    std::clock_t start;
    double duration;

    std::cout << "Starting std::cout test." << std::endl;
    start = std::clock();

    for (int i = 0; i < 1000; i++)
        std::cout << teststring;
    /* Display timing results, code trimmed for brevity */

    for (int i = 0; i < 1000; i++) {
        std::printf(teststring);
        std::fflush(stdout);
    }
    /* Display timing results, code trimmed for brevity */
    return 0;
}

При этом вы будете тестировать ничего, кроме различий между вызовами функций printf и cout. Вы не понесете никаких различий из-за множества вызовов << и т.д. Если вы попробуете это, я подозреваю, что вы получите совсем другой результат.

Ответ 2

Попробуйте следующее:

#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <iostream>

int main(int argc, char* argv[])
{
#if defined(NOSYNC)
    std::cout.sync_with_stdio(false);
#endif

    std::cout << "Starting std::cout test." << std::endl;

    std::clock_t start = std::clock();

    for (int i = 0; i < 1000; i++)
    {   
        std::cout << "Hello, World! (" << i << ")" << std::endl;
    }   

    clock_t mid = std::clock();

    for (int i = 0; i < 1000; i++)
    {   
        std::printf("Hello, World! (%i)\n", i); 
        std::fflush(stdout);
    }   

    std::clock_t end = std::clock();

    std::cout << "Time taken: P1 " << ((mid-start)*1.0/CLOCKS_PER_SEC) << std::endl;

    std::cout << "Time taken: P2 " << ((end-mid)*1.0/CLOCKS_PER_SEC) << std::endl;


    return 0;
}

Тогда я получаю:

> g++ -O3 t13.cpp
> ./a.out
# lots of lines deleted
Time taken: P1 0.002517
Time taken: P2 0.001872

> g++ -O3 t13.cpp -DNOSYNC   
> ./a.out
# lots of lines deleted
Time taken: P1 0.002398
Time taken: P2 0.001878

Таким образом, времена P2 не меняются.
Но вы получаете улучшение P1 раз (т.е. std:: cout) с помощью std::cout.sync_with_stdio(false);. Becuase код больше не пытается синхронизировать два потока (std:: cout stdout). Что, если вы пишете чистый С++ и только с использованием std:: cout не проблема.

Ответ 3

использовать

cout << "\n";

чтобы предотвратить буферизацию. гораздо быстрее

Ответ 4

Около 10 лет назад Скотт Майерс проверил эффективность iostream и scanf/printf. Зависит от компилятора и среды, иногда scanf/printf на 20% быстрее, чем iostream, иногда даже на 200% быстрее. Но iostream никогда не был быстрее, чем scanf/printf. Согласно другим двум приведенным примерам, scanf/printf все еще быстрее, чем iostream. Однако Мейерс сказал, что "по действительно полезной программе не было бы никаких различий". Согласно стилю программирования Google ([http://google-styleguide.googlecode.com/svn/trunk/cppguide.html]), потоки не должны использоваться, кроме журнала. Замена iostream заключается в инкапсуляции scanf/printf самостоятельно.