Is printf, fprintf, or cout, etc. faster?

closed account (42TXGNh0)
In two situations:

1. To output a single character.
Which of the following is the fastest to do the job?
A) putchar('*');
B) printf("%c",'*');
C) fprintf(stdout,"%c",'*');
D) cout << '*';

2. To output a single string.
Which of the following is the fastest to do the job?
A) printf("Me.");
B) printf("%s","Me.");
C) fprintf(stdout,"Me.");
D) fprintf(stdout,"%s","Me.");
E) cout << "Me.";

You may add options to show more possibilities.
Last edited on
> Is printf, fprintf, or cout, etc. faster?
The answer is always "it depends".

It depends on your OS (terminal driver, file system etc etc).
It depends on your compiler.
It depends on the quality of your standard library implementations.
It depends on what optimisations your compiler makes at various levels.

In short, stop worrying about micro-optimisations and make sure your "big picture" choices of algorithms and data structures are correct.

Because there is no compiler that will save you from the fire if you write your own crusty bubble sort, and have it magically replace it with qsort (for example). Get the algorithm wrong, and you're out by orders of magnitude. Tweaking the I/O might lose/gain by a factor of 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
$ cat foo.cpp
#include <iostream>
#include <cstdio>
using namespace std;

void f1 ( ) {
  putchar('*');
}
void f2 ( ) {
  printf("%c",'*');
}
void f3 ( ) {
  fprintf(stdout,"%c",'*');
}
void f4 ( ) {
  cout << '*';
}
void f5 ( ) {
  printf("Me.");
}
void f6 ( ) {
  printf("%s","Me.");
}
void f7 ( ) {
  fprintf(stdout,"Me.");
}
void f8 ( ) {
  fprintf(stdout,"%s","Me.");
}
void f9 ( ) {
  cout << "Me.";
}

$ g++ -S -c foo.cpp
$ fgrep -v '.' foo.s
_Z2f1v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$42, %edi
	call	putchar
	nop
	popq	%rbp
	ret
_Z2f2v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$42, %edi
	call	putchar
	nop
	popq	%rbp
	ret
_Z2f3v:
	pushq	%rbp
	movq	%rsp, %rbp
	movq	stdout(%rip), %rax
	movq	%rax, %rsi
	movl	$42, %edi
	call	fputc
	nop
	popq	%rbp
	ret
_Z2f4v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$42, %esi
	movl	$_ZSt4cout, %edi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c
	nop
	popq	%rbp
	ret
_Z2f5v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$0, %eax
	call	printf
	nop
	popq	%rbp
	ret
_Z2f6v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$0, %eax
	call	printf
	nop
	popq	%rbp
	ret
_Z2f7v:
	pushq	%rbp
	movq	%rsp, %rbp
	movq	stdout(%rip), %rax
	movq	%rax, %rcx
	movl	$3, %edx
	movl	$1, %esi
	call	fwrite
	nop
	popq	%rbp
	ret
_Z2f8v:
	pushq	%rbp
	movq	%rsp, %rbp
	movq	stdout(%rip), %rax
	movq	%rax, %rcx
	movl	$3, %edx
	movl	$1, %esi
	call	fwrite
	nop
	popq	%rbp
	ret
_Z2f9v:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$_ZSt4cout, %edi
	call	_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
	nop
	popq	%rbp
	ret

$ g++ -S -c -O2 foo.cpp
$ fgrep -v '.' foo.s
_Z2f1v:
	movq	stdout(%rip), %rsi
	movl	$42, %edi
	jmp	_IO_putc
_Z2f2v:
	movl	$42, %edi
	jmp	putchar
_Z2f3v:
	movq	stdout(%rip), %rsi
	movl	$42, %edi
	jmp	fputc
_Z2f4v:
	subq	$24, %rsp
	movl	$1, %edx
	movl	$_ZSt4cout, %edi
	leaq	7(%rsp), %rsi
	movb	$42, 7(%rsp)
	movq	%fs:40, %rax
	movq	%rax, 8(%rsp)
	xorl	%eax, %eax
	call	_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
	movq	8(%rsp), %rax
	xorq	%fs:40, %rax
	addq	$24, %rsp
	ret
	call	__stack_chk_fail
_Z2f5v:
	movl	$1, %edi
	xorl	%eax, %eax
	jmp	__printf_chk
_Z2f6v:
	movl	$1, %edi
	xorl	%eax, %eax
	jmp	__printf_chk
_Z2f7v:
	movq	stdout(%rip), %rcx
	movl	$3, %edx
	movl	$1, %esi
	jmp	fwrite
_Z2f8v:
	movq	stdout(%rip), %rcx
	movl	$3, %edx
	movl	$1, %esi
	jmp	fwrite
_Z2f9v:
	movl	$3, %edx
	movl	$_ZSt4cout, %edi
	jmp	_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l


Even without optimisations, GCC sees through "printf("%c",'*');" and just calls putchar with the obvious attempt to output a single char.

Topic archived. No new replies allowed.