Я где-то читал, что snprintf быстрее, чем ostringstream. У кого-нибудь есть опыт с этим? Если да, то почему это быстрее.
Почему snprintf быстрее ostringstream или нет?
Ответы (9)
std::ostringstream
не требуется, чтобы он был медленнее, но, как правило, он работает медленнее. На веб-сайте FastFormat есть несколько тестов.
Дизайн стандартной библиотеки для потоков поддерживает гораздо больше, чем snprintf
. Дизайн должен быть расширяемым и включает protected
virtual
методы, которые вызываются общедоступными методами. Это позволяет вам быть производным от одного из потоковых классов с гарантией того, что если вы перегрузите метод protect
ed, вы получите желаемое поведение. Я считаю, что компилятор может избежать накладных расходов на вызов функции virtual
, но я не знаю ни одного компилятора, который бы это делал.
Кроме того, в потоковых операциях часто используются внутренние растущие буферы; что подразумевает относительно медленное выделение памяти.
printf
поддерживает локали, как и iostream
. @kotlinski: Они также безопасны для потоков.
- person ; 09.07.2012
snprintf
и другие функции. Я удалил ссылку на локали.
- person Max Lybbert; 10.07.2012
Мы заменили некоторые строковые потоки во внутренних циклах на 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 }
но я очень доволен общей производительностью струнных потоков.
Некоторые ребята, возможно, скажут вам, что функции не могут быть быстрее друг друга, но их реализация может. Правильно, я думаю, что согласен.
Вы вряд ли когда-нибудь заметите разницу, кроме тестов. Причина того, что потоки C ++ обычно имеют тенденцию быть медленнее, заключается в том, что они гораздо более гибкие. Гибкость чаще всего достигается либо за счет времени, либо за счет роста кода.
В этом случае потоки C ++ основаны на потоковых буферах. Сами по себе потоки - это всего лишь оболочка, которая хранит флаги форматирования и ошибок на месте и вызывает правильные i/o
фасеты стандартной библиотеки c ++ (например, num_put для печати чисел), которые печатают значения, хорошо отформатированные, в базовый поток. -буфер, подключенный к потоку c ++.
Все эти механизмы - фасеты и буферы - реализуются виртуальными функциями. Хотя на самом деле нет отметки примечание, эти функции должны быть реализованы медленнее, чем c stdio pendants, этот факт сделает их несколько медленнее, чем использование функций c stdio в обычном режиме (я тестировал это некоторое время назад с gcc / libstdc ++ и на самом деле заметил замедление, но которое вы почти не замечаете при повседневном использовании).
Абсолютно это зависит от реализации.
Но если вы действительно хотите знать, напишите две небольшие программы и сравните их. Вам нужно будет включить типичное использование того, что вы имеете в виду, две программы должны будут генерировать одну и ту же строку, и вы должны использовать профилировщик для просмотра информации о времени.
Тогда ты бы знал.
Одна из проблем, вероятно, будет заключаться в том, что безопасность типов, добавленная ostringstream
, несет дополнительные накладные расходы. Однако я не проводил никаких измерений.
Как сказано в litb, стандартные потоки поддерживают многие вещи, которые нам не всегда нужны. Некоторые реализации потоков избавляются от этой никогда не использовавшейся гибкости, например, см. FAStream.
Вполне возможно, потому что sprintf
является частью CRT, написанной на ассемблере. ostringstream
является частью STL и, вероятно, написан немного более обобщенно, и имеет код ООП / накладные расходы, с которыми нужно работать.
sprintf
на ассемблере, кроме, возможно, упражнения в мазохизме. Начиная с UNIX V6, сама библиотека времени выполнения C была написана на C (за исключением крошечной горстки вещей, которые невозможно написать на C, например setjmp
).
- person zwol; 19.09.2012
Да, если вы запустите приведенную ниже функцию для нескольких миллионов чисел с помощью Visual C ++ 5.0, первая версия займет примерно вдвое больше времени, чем вторая, и выдаст тот же результат.
Компиляция жестких циклов в .exe и запуск Windows timethis something.exe' or the Linux
time something »- вот как я исследую большинство своих любопытных вопросов, связанных с производительностью. ("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
}
void Hexx32Bit(...) {}
- person Eric; 23.03.2018
Одна из причин, по которой я знаю, что семейство функций printf быстрее, чем соответствующие функции C ++ (cout, cin и другие потоки), заключается в том, что последние выполняют проверку типов. Поскольку это обычно связано с некоторыми запросами к перегруженным операторам, это может занять некоторое время.
Фактически, на соревнованиях по программированию часто рекомендуется использовать printf et al, а не cout / cin именно по этой причине.
<iostream>
ужасен.
- person Tom; 12.12.2009