printf
является медленной функцией, если вы выводите только постоянные строки, потому что printf
должен сканировать каждый символ для спецификатора формата (%
). Функции, такие как puts
, являются значительно быстрее для длинных строк, потому что они могут в основном просто memcpy
входная строка в выходной буфер ввода-вывода.
Многие современные компиляторы (GCC, Clang, возможно, другие) имеют оптимизацию, которая автоматически преобразует printf
в puts
, если входная строка является константной строкой без спецификаторов формата, которая заканчивается символом новой строки. Так, например, составление следующий код:
printf("line 1\n");
printf("line 2\n");
printf("line 3"); /* no newline */
результаты в следующей сборке (лязг 703.0.31, cc test.c -O2 -S
):
...
leaq L_str(%rip), %rdi
callq _puts
leaq L_str.3(%rip), %rdi
callq _puts
leaq L_.str.2(%rip), %rdi
xorl %eax, %eax
callq _printf
...
другими словами, puts("line 1"); puts("line 2"); printf("line 3");
.
Если долго printf
строка делает не конца с новой строкой, то ваша производительность может быть значительна хуже, чем если бы вы сделали кучу printf
вызовов с новой строкой с завершающими строками, просто из-за эту оптимизацию. Для того, чтобы продемонстрировать, рассмотрят следующую программу:
#include <stdio.h>
#define S "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
#define L S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S S
/* L is a constant string of 4000 'a's */
int main() {
int i;
for(i=0; i<1000000; i++) {
#ifdef SPLIT
printf(L "\n");
printf(S);
#else
printf(L "\n" S);
#endif
}
}
Если SPLIT
не определена (продуцирующие один printf
, без завершающего символа новой строки), время выглядит следующим образом:
[08/11 11:47:23] /tmp$ cc test.c -O2 -o test
[08/11 11:47:28] /tmp$ time ./test > /dev/null
real 0m2.203s
user 0m2.151s
sys 0m0.033s
Если SPLIT
определен (производство два printf
с, одна с завершающим символом новой строкой, другой без), время выглядит следующим образом:
[08/11 11:48:05] /tmp$ time ./test > /dev/null
real 0m0.470s
user 0m0.435s
sys 0m0.026s
Итак, вы можете видеть, что в этом случае разделение printf
на две части на самом деле дает ускорение в 4 раза. Конечно, это крайний случай, но он иллюстрирует, как printf
можно оптимизировать в зависимости от ввода. (Обратите внимание, что использование fwrite
еще быстрее - 0,197 с, поэтому вам следует подумать об использовании этого, если вы действительно хотите скорость!).
tl; dr: если вы печатаете только большие постоянные строки, полностью избегайте printf
и используйте более быструю функцию, например puts
или fwrite
.
Ваш синтаксис C недействителен. –
@ammoQ; Кажется верным мне. – haccks
@ammoQ Действительно. – LPs