Как сравниваются скорости выполнения snprintf и strncat? - PullRequest
2 голосов
/ 23 августа 2011

У меня есть программа, которая объединяет некоторое количество строк в буфере.

Я раньше использовал strncpy. Изучив некоторые предложения по использованию snprintf вместо strncat, я переключился на snprintf. Тем не менее, я заметил задержку выполнения этой части программы (конкатенация строк). Возможно ли, что snprintf может замедлить скорость выполнения программы? Если нет, то я буду искать другие факторы в моей программе.

if(iOffset<MAX_BUFF_SIZE && iOffset>0)
{
  ....... 
  iOffset += snprintf(cBuff+iOffset, sizeof(cBuff)-iOffset, "%s", "String1");
  ...... 
}

Я повторяю приведенный фрагмент кода примерно 12 раз, чтобы добавить строки в cBuff.

Редактировать: повторяется 12 раз через каждые 1 сек.

Ответы [ 6 ]

4 голосов
/ 23 августа 2011

strncat страдает от проблемы Schlemiel the Painter .Способ, которым вы используете snprintf, не подходит (хотя можно использовать и strncat таким же образом, и обойти проблему таким образом).

4 голосов
/ 23 августа 2011

Есть несколько предложений, которые приходят на ум:

  • не оптимизируйте свою программу слишком рано
  • когда вы будете готовы к оптимизации, используйте инструмент, такой как профилировщик, чтобы узнать, где реальные замедления

Если вы не знакомы с профилированием или действительно хотите узнать подробности синхронизации, вы всегда можете включить таймеры вокруг кода. Смотрите ссылки на gettimeofday () или clock () и соответствующие предупреждения об этих кодах. По сути, вы можете получить время до исполнения, время после и сравнить их. Закомментируйте свою строку кода, вставьте старый код и укажите время.

С учетом всего сказанного ... это часть того, что профилировщик делает для вас. Выяснить, «почему» что-то медленно, иногда сложно, потому что могут быть другие соображения (например, на аппаратном уровне), о которых вы не знаете.

Выполнение функции 12 раз, вероятно, тривиально по сравнению с общим временем выполнения программы.

1 голос
/ 23 августа 2011

Копирование идиомы «повторной конкатенации» и просто использование snprintf для этого не соответствует предложению избегать strcat.Вы должны сделать что-то вроде:

snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);

Это будет намного быстрее, чем повторные вызовы snprintf, что повлечет за собой много накладных расходов на каждый вызов, и на самом деле это будет правильно использовать идиому.

1 голос
/ 23 августа 2011

Предполагая, что вы принимаете во внимание проблему, о которой говорил Крис Джестер-Янг, учтя проблему " Schlemiel the Painter ", вы, скорее всего, обнаружите, что в сравнении между собой strncat() быстрее, чем snprintf() - в том смысле, в каком вы его используете.

snprintf() имеет (хотя и незначительные, в данном случае) накладные расходы на необходимость разбора строки формата, чего нет у strncat().

Предоставленный вами фрагмент кода достаточно отличается от примера, приведенного в связанном вопросе , чтобы потенциально изменить сравнение.

Как уже упоминал Стивен, для большинства платформ, работающих strncpy() 12 раз по сравнению с snprintf(), разница должна быть незначительной. Здесь было бы полезно использовать профилировщик, чтобы убедиться, что вы сосредоточены на правильной области.


В приведенном вами примере вы пытаетесь добавить строку const в ваш буфер. Если это то, что вы делаете в своем реальном коде (а не просто в качестве простого примера) и копирование строки действительно значительная область времени выполнения, вы можете оптимизировать эту область.

Одним из распространенных методов оптимизации является поиск вычислений, которые можно предварительно вычислить во время компиляции, а не во время выполнения. Если вас интересует только обработка константных строк, вы можете эффективно рассчитать длину строк и затем использовать memcpy() вместо strncpy() для выполнения добавления строки. memcpy() обычно очень хорошо оптимизирован для вашей платформы.

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

0 голосов
/ 30 июля 2013

Люди, которые упоминали не оптимизировать рано после того, как вы заметили замедление, глупы. В этом случае вам даже не нужно запускать профилировщик. У вас уже есть эмпирические доказательства того, что переключение на snprintf замедлило вашу программу.

Я работаю в финансовой индустрии, где производительность является ключевой и почти всегда предпочитаю sprintf, а не snprintf. С его помощью можно быстро и стабильно создавать приложения в жестко контролируемой среде.

0 голосов
/ 23 августа 2011

Я не профилировщик, поэтому не могу точно сказать, что медленно.

Как упоминает @chris, strncat может выполнять больше работы, чем нужно, чтобы снова и снова находить конец строки назначения. Возможно, вам удалось смягчить это, так как, по-видимому, вы отслеживаете занимаемое пространство, поэтому вы можете начинать с конца при каждом последующем вызове.

С другой стороны, snprintf, вероятно, должен выполнять дополнительную работу по сравнению с strcat или strcpy, потому что он должен анализировать "% s" при каждом вызове, чтобы выяснить, как обращаться со списком переменных аргументов.

Меня не удивляет, что strncat может работать быстрее, особенно при отсутствии агрессивных уровней оптимизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...