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 самостоятельно.