Подтвердить что ты не робот

Почему snprintf быстрее, чем ostringstream, или это так?

Я где-то читал, что snprintf быстрее, чем ostringstream. У кого-нибудь есть опыт? Если да, то почему это происходит быстрее.

4b9b3361

Ответ 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 именно по этой причине.