Почему использование std :: endl с ostringstream влияет на скорость вывода?

Я рассчитываю разницу между различными способами печати текста на стандартный вывод. Я тестирую cout, printf, а также ostringstream используя оба \n а также std::endl, Я ожидал std::endl иметь значение с cout (и это сделал), но я не ожидал, что это замедлит выход с ostringstream, Я думал, используя std::endl бы просто написать \n к потоку, и это все еще только покраснеть один раз. Что тут происходит? Вот весь мой код:

// cout.cpp
#include <iostream>

using namespace std;

int main() {
for (int i = 0; i < 10000000; i++) {
cout << "Hello World!\n";
}
return 0;
}

// printf.cpp
#include <stdio.h>

int main() {
for (int i = 0; i < 10000000; i++) {
printf("Hello World!\n");
}
return 0;
}

// stream.cpp
#include <iostream>
#include <sstream>

using namespace std;

int main () {
ostringstream ss;
for (int i = 0; i < 10000000; i++) {
ss << "stream" << endl;
}
cout << ss.str();
}

// streamn.cpp
#include <iostream>
#include <sstream>

using namespace std;

int main () {
ostringstream ss;
for (int i = 0; i < 10000000; i++) {
ss << "stream\n";
}
cout << ss.str();
}

А вот и мой Makefile

SHELL:=/bin/bash

all: cout.cpp printf.cpp
g++ cout.cpp -o cout.out
g++ printf.cpp -o printf.out
g++ stream.cpp -o stream.out
g++ streamn.cpp -o streamn.out
time:
time ./cout.out > output.txt
time ./printf.out > output.txt
time ./stream.out > output.txt
time ./streamn.out > output.txt

Вот что я получаю, когда бегу make с последующим make time

time ./cout.out > output.txt

real    0m1.771s
user    0m0.616s
sys 0m0.148s
time ./printf.out > output.txt

real    0m2.411s
user    0m0.392s
sys 0m0.172s
time ./stream.out > output.txt

real    0m2.048s
user    0m0.632s
sys 0m0.220s
time ./streamn.out > output.txt

real    0m1.742s
user    0m0.404s
sys 0m0.200s

Эти результаты согласуются.

9

Решение

std::endl вызывает сброс потока, что сильно замедляет печать. Увидеть http://en.cppreference.com/w/cpp/io/manip/endl

Часто рекомендуется не использовать std::endl если вы действительно не хотите, чтобы поток был очищен. Если это действительно важно для вас, зависит от вашего варианта использования.

По поводу почему flush оказывает влияние на производительность даже в потоке ostring (где не должно происходить сбрасывание): кажется, что реализация требуется, по крайней мере, для создания сторожевых объектов. Те, кто должен проверить good а также tie из ostream, Призыв к pubsync должен быть в состоянии быть оптимизирован. Это основано на моем чтении libcpp и libstdc ++.

После некоторого прочтения интересный вопрос, как представляется, заключается в следующем: basic_ostringstream::flush действительно требуется построить часовой объект? Если нет, то мне кажется, что это проблема качества реализации. Но я на самом деле думаю, что это нужно, потому что даже basic_stringbug может измениться, чтобы его badbit задавать.

14

Другие решения

Каждая операция вывода в потоке выполняется в несколько этапов:

  • Он проверяет, находится ли поток в хорошей форме.
  • Он проверяет, нужно ли сбрасывать какой-либо другой поток.
  • Последовательность символов производится.
  • Он проверяет, достаточно ли места для написанных символов.
  • Использование endl вызывает дополнительную виртуальную функцию в буфере потока.

Я лично ожидал бы, что дополнительный вызов виртуальной функции на самом деле имеет относительно небольшое влияние по сравнению с другими операциями. Вы можете проверить это предположение, также профилировав этот вывод:

out << "stream" << '\n';

… или даже

out << "stream" << out.widen('\n');

Тем не менее, есть ряд улучшений, которые реализация потока может применить, чтобы сократить проверки. Конечно, будет ли это сделано, зависит от реализации.

1

С помощью std::endl эквивалентно письму

stream << "\n";
stream.flush();

Не использовать std::endl если вы на самом деле не хотите инициировать сброс, и / или не заботитесь о производительности на выходе.

Кроме того, не беспокойтесь о разных концах строк на разных платформах, ваша реализация переведет "\n" до конца строки, соответствующего вашей платформе.

0
По вопросам рекламы [email protected]