Я где-то читал, что snprintf быстрее, чем ostringstream. У кого-нибудь есть опыт? Если да, то почему это происходит быстрее.
Почему snprintf быстрее, чем ostringstream, или это так?
Ответ 1
std::ostringstream
не требуется, чтобы быть медленнее, но при реализации он обычно медленнее. На веб-сайте FastFormat есть некоторые ориентиры.
Стандартная библиотека для потоков поддерживает гораздо больше, чем snprintf
. Конструкция предназначена для расширения и включает методы protected
virtual
, которые вызываются публично открытыми методами. Это позволяет вам получить один из классов потоков, при условии, что если вы перегрузите метод protect
ed, вы получите нужное поведение. Я считаю, что компилятор мог избежать накладных расходов на вызов функции virtual
, но я не знаю о компиляторах, которые это делают.
Кроме того, операции потока часто используют встроенные буферы внутри; что подразумевает относительно медленное выделение памяти.
Ответ 2
Некоторые ребята, возможно, расскажут вам, что функции не могут быть быстрее друг друга, но их реализация может. Правильно, я думаю, что соглашусь.
Вы вряд ли заметите разницу в сравнении с эталонами. Причина, по которой потоки С++ обычно имеют тенденцию быть медленнее, состоит в том, что они намного более гибкие. Гибкость чаще всего происходит за счет роста времени или кода.
В этом случае потоки С++ основаны на потоковых буферах. Сам по себе потоки - это всего лишь корпус, который содержит флаги форматирования и ошибок, и называет правильные грани i/o
стандартной библиотеки С++ (например, num_put для печати чисел), которые печатают значения, хорошо отформатированные, в базовый поток-буфер, подключенный к потоку С++.
Все эти механизмы - грани и буферы реализованы виртуальными функциями. Несмотря на то, что на самом деле нет заметки, эти функции должны быть реализованы медленнее, чем c stdio pendants, что делает их несколько медленнее, чем обычно использовать функции stdio (я оценил, что некоторое время назад с gcc/libstdС++ и фактически заметил замедление - но вы вряд ли заметите в повседневном использовании).
Ответ 3
Мы заменили некоторые строковые потоки во внутренних циклах на sprintf (используя статически распределенные буферы), и это имело большое значение, как в msvc, так и в gcc. Я полагаю, что управление динамической памятью этого кода:
{ char buf[100]; int i = 100; sprintf(buf, "%d", i); // do something with buf }
намного проще, чем
{ std::stringstream ss; int i = 100; ss << i; std::string s = ss.str(); // do something with s }
но я очень доволен общей производительностью строк.
Ответ 4
Абсолютно это специфично для реализации.
Но если вы действительно хотите знать, напишите две небольшие программы и сравните их. Вам нужно будет включить типичное использование для того, что вы имеете в виду, обе программы должны будут генерировать одну и ту же строку, и вы бы использовали профилировщик для просмотра информации о времени.
Тогда вы бы знали.
Ответ 5
Одна из проблем, вероятно, заключалась бы в том, что безопасность типа, добавленная с помощью ostringstream
, несет дополнительные накладные расходы. Однако я не сделал никаких измерений.
Ответ 6
Вполне возможно, что поскольку sprintf
является частью CRT, написанной в сборке. ostringstream
является частью STL и, вероятно, немного более обобщенно написан и имеет код OOP/накладные расходы.
Ответ 7
Как litb сказал, стандартные потоки поддерживают многие вещи, которые нам не всегда нужны. Некоторые реализации потоков избавляются от этой неизменной гибкости, например, FAStream.
Ответ 8
Да, если вы запустите функцию ниже на несколько миллионов номеров с Visual С++ 5.0, первая версия займет примерно в два раза длиннее второй и выдаст тот же результат.
Компилирование жестких циклов в .exe и запуск Windows timethis something.exe' or the Linux
время, что-то, это то, как я исследую большинство моих ракурсов. (`timethis 'доступен в Интернете где-то)
void Hex32Bit(unsigned int n, string &result)
{
#if 0
stringstream ss;
ss
<< hex
<< setfill('0')
<< "0x" << setw(8) << n
;
result = ss.str();
#else
const size_t len = 11;
char temp[len];
_snprintf(temp, len, "0x%08x", n);
temp[len - 1] = '\0';
result = temp;
#endif
}
Ответ 9
Одна из причин, по которой я знаю, что семейство функций printf быстрее, чем соответствующие функции С++ (cout, cin и другие потоки), заключается в том, что последние выполняют проверку типов. Поскольку это обычно связано с некоторыми запросами перегруженных операторов, это может занять некоторое время.
На самом деле, в соревнованиях по программированию часто рекомендуется использовать printf и другие, а не cout/cin именно по этой причине.